【问题标题】:Unable to Identify User Context in SignalR hub decorated with "Authorize" attribute无法识别使用“授权”属性装饰的 SignalR 集线器中的用户上下文
【发布时间】:2014-10-19 23:25:34
【问题描述】:

服务器

MVC 5 WebApi 2 中的 SignalR 集线器, 安全性:不记名令牌

客户

C# 类使用 HttpWebRequest 从 WebApi 控制器 /Token 端点检索不记名令牌

我使用herehere 描述的模式将不记名令牌传递给我的 AuthorizeAttribute 子类。

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

这里是覆盖方法:

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;
 }

当我在没有授权属性的情况下运行集线器并在“OnConnected”覆盖中设置断点时,Context.User 属性也为空。

任何帮助将不胜感激。

丰富

【问题讨论】:

    标签: signalr


    【解决方案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;
      }
    

    【讨论】:

      【解决方案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 = { 承载: 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、signal r 的解决方案,用于使用承载令牌对 SignalR 集线器进行身份验证。

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-04-06
        • 2021-05-27
        • 1970-01-01
        • 2015-09-07
        • 2016-12-22
        • 1970-01-01
        • 2016-07-23
        • 2021-10-22
        相关资源
        最近更新 更多