【问题标题】:SignalR hub Authorize attribute doesn't workSignalR 集线器授权属性不起作用
【发布时间】:2019-06-19 21:05:44
【问题描述】:

我正在使用 SignalR 向 Angular 发送通知。但我想让它特定于用户。用户使用 azure ad 登录。我在集线器上有一个 [Authorize],但授权失败。但在我的控制器中它工作正常。

到目前为止我已经尝试过。我从微软网站尝试了这个 services.AddAuthentication。 https://docs.microsoft.com/en-us/aspnet/core/signalr/authn-and-authz?view=aspnetcore-2.2 但是随后我的控制器无法验证令牌,因为令牌不在 url 中,而是在标头中。

startup.cs:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddOptions();

        // Add custom configuration/resource files
        services.ConfigureSettings(Configuration);
        services.Configure<GzipCompressionProviderOptions>(options =>
            options.Level = System.IO.Compression.CompressionLevel.Fastest
        );

        services.AddResponseCompression(options =>
        {
            options.EnableForHttps = true;
            options.Providers.Add<GzipCompressionProvider>();
        });

        services.AddCors(options =>
        {
            options.AddPolicy("CorsPolicy",
                builder => builder
                    .AllowAnyOrigin()
                    .AllowAnyMethod()
                    .AllowAnyHeader()
                    .AllowCredentials()
                    .WithOrigins("http://localhost:4200"));
        });

        services.AddAuthentication(AzureADDefaults.BearerAuthenticationScheme)
            .AddAzureADBearer(options => Configuration.Bind("AzureAD", options));           

        services.AddSignalR();

        // Add framework services.
        services.AddMvc(options =>
        {        
            options.Filters.Add(new ValidateModelStateFilter());

        }).AddJsonOptions(options =>
        {
            options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
            options.SerializerSettings.ContractResolver =
                new CamelCasePropertyNamesContractResolver();
        });

我的中心:

 [Authorize]
 public class NotifyHub : Hub<ITypedHubClient>
   {
    public Task SendMessage(string user, string message)
    {

        return Clients.Client(Context.ConnectionId)
               .BroadcastMessage("ReceiveMessage", user, message);
    }

    public Task Log(string email)
    {
        Debug.WriteLine(Context.ConnectionId);

        return Clients.Caller.BroadcastMessage("succes", "string");
    }

    public override Task OnConnectedAsync()
    {

        return base.OnConnectedAsync();
    }
}

角度 SignalR 服务:

private createConnection() {     
   this._hubConnection = new HubConnectionBuilder()  
  .withUrl('https://localhost:44334/notify', { accessTokenFactory: () => { 
   return this.adalSvc.accessToken }  })      
  .build(); 
}  

我想让用户进入我的集线器,这样我就可以将用户映射到连接 ID。

【问题讨论】:

    标签: c# authentication signalr azure-active-directory signalr-hub


    【解决方案1】:

    你没有显示你的using 语句,我看到你也在使用 MVC。也许您使用了错误的 AuthorizeAttribute?

    确保您使用的是 Microsoft.AspNet.SignalR.AuthorizeAttribute 而不是 MVC。

    【讨论】:

      【解决方案2】:

      SignalR 的问题是它无法修改标头来发送令牌所以

             services.AddAuthentication(AzureADDefaults.BearerAuthenticationScheme)
             .AddAzureADBearer(options => Configuration.Bind("AzureAD", options));  
      

      不适用于 SignalR,因为 URL 中需要令牌。

      以下内容同时适用于经过身份验证的 API 调用和经过身份验证的 SignalR 连接

      services.AddAuthentication(options = >{
          options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
          options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
      }).AddJwtBearer(options = >{
         options.RequireHttpsMetadata = false;
         options.SaveToken = true;
         options.Authority = "https://login.microsoftonline.com/" + Configuration["AzureAd:TenantId"];
      options.TokenValidationParameters = new TokenValidationParameters() {
          // These need to be set correctly after checking that it works
          ValidateAudience = false,
          ValidateLifetime = false,
          ValidateIssuer = false,
          ValidateIssuerSigningKey = false,
          ValidateActor = false
      };
      options.Events = new JwtBearerEvents {
          OnMessageReceived = ctx = >{
              if (ctx.Request.Query.ContainsKey("access_token")) 
                   ctx.Token = ctx.Request.Query["access_token"];
              return Task.CompletedTask;
          }
      };
      

      });

      你可以在你的中心测试这个

             public override async Task OnConnectedAsync()
             {
               var Oid = (Context.User.FindFirst(c => 
                         c.Type == "http://schemas.microsoft.com/identity/claims/objectidentifier"))?.Value;
               Debug.WriteLine(Oid);
             }
      

      API 和 SignalR 的 [Authorize] 属性均来自

      using Microsoft.AspNetCore.Authorization;
      

      【讨论】:

        猜你喜欢
        • 2014-10-27
        • 1970-01-01
        • 2015-09-07
        • 1970-01-01
        • 2019-07-23
        • 1970-01-01
        • 1970-01-01
        • 2019-08-10
        相关资源
        最近更新 更多