问题
I want to authenticate users when they connect to the signalr server. The clients are javascript and are cross-domain. I tried using this example and the AuthorizeHubMethodInvocation
gets called but the AuthorizeHubConnection
never gets called.
I created a new class AuthTicketAttribute
where i override the two methods,
public class AuthTicketAttribute : AuthorizeAttribute
{
public override bool AuthorizeHubConnection(HubDescriptor hubDescriptor, IRequest request)
{
return base.AuthorizeHubConnection(hubDescriptor, request);
}
public override bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubIncomingInvokerContext, bool appliesToMethod)
{
return base.AuthorizeHubMethodInvocation(hubIncomingInvokerContext, appliesToMethod);
}
}
and then i added it in the signalr map function
var authorizer = new AuthTicketAttribute();
var module = new AuthorizeModule(authorizer, authorizer);
And then i tried debugging the code, only the AuthorizeHubMethodInvocation
gets called when i call a method, the AuthorizeHubConnection
doesn't get called when i connect. Any idears?
I then though maybe i could move the code setting the server.User
in the enviroment from the AuthorizeHubConnection
to the AuthorizeHubMethodInvocation
,
public override bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubIncomingInvokerContext, bool appliesToMethod)
{
IList<Claim> claims = new List<Claim>
{
new Claim(ClaimTypes.NameIdentifier, "The users username")
};
ClaimsIdentity claimsIdentity = new ClaimsIdentity(claims, "Basic", ClaimTypes.NameIdentifier, ClaimTypes.Role);
var environment = hubIncomingInvokerContext.Hub.Context.Request.Environment;
environment["server.User"] = new ClaimsPrincipal(claimsIdentity);
hubIncomingInvokerContext.Hub.Context = new HubCallerContext(new ServerRequest(environment), hubIncomingInvokerContext.Hub.Context.ConnectionId);
return true;
}
but then i get a NullReferenceException
when i set the server.User
on the environment object, but none of the objects are null.
at System.Web.HttpContext.SetPrincipalNoDemand(IPrincipal principal, Boolean needToSetNativePrincipal)
at System.Web.HttpContext.set_User(IPrincipal value)
at Microsoft.Owin.Host.SystemWeb.OwinCallContext.Microsoft.Owin.Host.SystemWeb.CallEnvironment.AspNetDictionary.IPropertySource.SetServerUser(IPrincipal value)
at Microsoft.Owin.Host.SystemWeb.CallEnvironment.AspNetDictionary.set_ServerUser(IPrincipal value)
at Microsoft.Owin.Host.SystemWeb.CallEnvironment.AspNetDictionary.PropertiesTrySetValue(String key, Object value)
at Microsoft.Owin.Host.SystemWeb.CallEnvironment.AspNetDictionary.System.Collections.Generic.IDictionary<System.String,System.Object>.set_Item(String key, Object value)
at LifeCommunicationServer.AuthTicketAttribute.AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubIncomingInvokerContext, Boolean appliesToMethod) in c:\Projects\TeamFoundation\LifeManager\CareManager-Master\LifeCommunicationServer\LifeCommunicationServer\AuthTicketAttribute.cs:line 62
at Microsoft.AspNet.SignalR.Hubs.AuthorizeModule.<>c__DisplayClass2b.<BuildIncoming>b__26(IHubIncomingInvokerContext context)
at Microsoft.AspNet.SignalR.Hubs.HubPipelineModule.<>c__DisplayClass1.<<BuildIncoming>b__0>d__3.MoveNext()
回答1:
I figurred out why the AuthorizeHubConnection was not called.
I hadn't subscribed to anything from the hub before starting the connection.
$.connection.myHub.client.something = function() {
};
$.connection.hub.start().done(function() {
alert('I'm connected!');
});
once i did this, it gets called.
回答2:
The answer above didn't work out for me.
The problem is that hubIncomingInvokerContext.Hub.Context.Request.Environment
behaves as an IDictionary
, but is in fact an Microsoft.Owin.Host.SystemWeb.CallEnvironment.AspNetDictionary
which does some extra checks when assigning key-value pairs (and throws while doing so).
My solution is to add the content to a real Dictionary
.
var environment = hubIncomingInvokerContext.Hub.Context.Request.Environment;
var copy = new Dictionary<string, object>(environment)
{
["server.User"] = new ClaimsPrincipal(claimsIdentity)
};
var serverRequest = new ServerRequest(copy);
hubIncomingInvokerContext.Hub.Context = new HubCallerContext(serverRequest, hubIncomingInvokerContext.Hub.Context.ConnectionId);
来源:https://stackoverflow.com/questions/28275341/signalr-authorizehubconnection