无法识别用"授权"装饰的SignalR集线器中的用户上下文。属性

时间:2014-08-26 15:04:44

标签: signalr

服务器

MVC 5 WebApi 2中的SignalR集线器, 安全:持票人令牌

客户

使用HttpWebRequest从WebApi控制器/令牌端点检索承载令牌的C#类

我使用了herehere描述的模式将持有者令牌传递给我的AuthorizeAttribute子类。

当AuthorizeHubConnection方法中的代码执行通过调用“secureDataFormat.Unprotect(token)”传递的票证时,该值始终为null。我已经确认通信两端的令牌是相同的。

这是覆盖方法:

public override bool AuthorizeHubConnection(AspNet.SignalR.Hubs.HubDescriptor hubDescriptor, IRequest request)
{
     var dataProtectionProvider = new DpapiDataProtectionProvider();

     var secureDataFormat = new TicketDataFormat(dataProtectionProvider.Create());
     var token = request.QueryString.Get("Bearer");
     var ticket = secureDataFormat.Unprotect(token);

     if (ticket != null && ticket.Identity != null && ticket.Identity.IsAuthenticated)
     {
       // set the authenticated user principal into environment so that it can be used in the future
       request.Environment["server.User"] = new ClaimsPrincipal(ticket.Identity);
       return true;
      }

      return false;
 }

当我在没有authorize属性的情况下运行hub并在“OnConnected”覆盖中设置断点时,Context.User属性也为null。

非常感谢任何协助。

2 个答案:

答案 0 :(得分:2)

这是我的解决方案,在Azure和本地工作。 AngularJS,Web API和SignalR request.Environment [“server.User”]此代码在Azure上不起作用。 首先,我创建自定义过滤器类。

[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
    public class QueryStringBearerAuthorizeAttribute : AuthorizeAttribute
    {
        public override bool AuthorizeHubConnection(Microsoft.AspNet.SignalR.Hubs.HubDescriptor hubDescriptor, IRequest request)
        {
            var _Authorization = request.QueryString.Get("Bearer");
        if (!string.IsNullOrEmpty(_Authorization))
        {
            var ticket = Startup.OAuthOptions.AccessTokenFormat.Unprotect(_Authorization);

            if (ticket != null && ticket.Identity != null && ticket.Identity.IsAuthenticated)
            {
                request.Environment["server.User"] = new ClaimsPrincipal(ticket.Identity);
                return true;
            }
        }
        return false;
        }
        public override bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubIncomingInvokerContext, bool appliesToMethod)
        {
            var connectionId = hubIncomingInvokerContext.Hub.Context.ConnectionId;
            var request=hubIncomingInvokerContext.Hub.Context.Request;
            var _Authorization = request.QueryString.Get("Bearer");
            if (!string.IsNullOrEmpty(_Authorization))
            {
                //var token = _Authorization.Replace("Bearer ", "");
                var ticket = Startup.OAuthOptions.AccessTokenFormat.Unprotect(_Authorization);

                if (ticket != null && ticket.Identity != null && ticket.Identity.IsAuthenticated)
                {
                    Dictionary<string, object> _DCI = new Dictionary<string, object>();
                    _DCI.Add("server.User", new ClaimsPrincipal(ticket.Identity));
                    hubIncomingInvokerContext.Hub.Context = new HubCallerContext(new ServerRequest(_DCI), connectionId);
                    return true;
                }
            }
            return false;
        }
}

然后在我从SignalR的所有连接中,我把

  

connection.qs = {Bearer:   localStorageService.get('authorizationData')。token};

我的启动课程

public void Configuration(IAppBuilder app)
        {
            app.Map("/signalr", map =>
            {
                map.UseCors(CorsOptions.AllowAll);
                var hubConfiguration = new HubConfiguration
                {
                    EnableDetailedErrors = true
                };
                var authorizer = new QueryStringBearerAuthorizeAttribute();
                var module = new AuthorizeModule(authorizer, authorizer);
                GlobalHost.HubPipeline.AddModule(module);
                map.RunSignalR(hubConfiguration);
            });
            GlobalHost.HubPipeline.AddModule(new LoggingPipelineModule());
            ConfigureAuth(app);
        }

它对我来说很完美,我不确定是否从头部发送问号字符串的令牌是一个安全问题。多数民众赞成我的解决方案使用angularjs,asp.net web api,信号r用于autenticate SignalR集线器和带有标记的令牌。

在您的集线器中,您可以通过这种方式访问​​用户变量

public ClaimsPrincipal _User { get { return Context.Request.Environment["server.User"] as ClaimsPrincipal; } }

答案 1 :(得分:1)

最后想出来了,我使用错误的库来解密令牌。 DpapiDataProtectionProvider用于自主机方案,我们托管在IIS中。这是正常运行的代码。

 public override bool AuthorizeHubConnection(Microsoft.AspNet.SignalR.Hubs.HubDescriptor    hubDescriptor, IRequest request)
 {
       var token = request.QueryString.Get("Bearer");
       var ticket = Startup.OAuthOptions.AccessTokenFormat.Unprotect(token);

        if (ticket != null && ticket.Identity != null && ticket.Identity.IsAuthenticated)
        {
             // set the authenticated user principal into environment so that it can be used in the future
             request.Environment["server.User"] = new ClaimsPrincipal(ticket.Identity);
             return true;
        }

       return false;
  }