SignalR AuthorizeHubConnection

可紊 提交于 2019-12-12 15:41:49

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!