简体   繁体   English

SignalR集线器Authorize属性不起作用

[英]SignalR hub Authorize attribute doesn't work

I'm using SignalR to send notification to angular. 我正在使用SignalR将通知发送到angular。 But i want to make it user specific. 但我想使其针对特定用户。 The user is logged in with azure ad. 用户使用天蓝色广告登录。 And i have a [Authorize] on the hub but the authorisation fails. 我在集线器上有一个[授权],但授权失败。 But in my controller it works fine. 但是在我的控制器中它可以正常工作。

What i have tried so far. 到目前为止我尝试过的。 I tried this services.AddAuthentication from the microsoft site. 我尝试了来自Microsoft网站的services.AddAuthentication。 https://docs.microsoft.com/en-us/aspnet/core/signalr/authn-and-authz?view=aspnetcore-2.2 But then my controller can't verify the token because the token isn't in the url but in the header. https://docs.microsoft.com/zh-cn/aspnet/core/signalr/authn-and-authz?view=aspnetcore-2.2但是我的控制器无法验证令牌,因为令牌不在URL中但在标题中

startup.cs: 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();
        });

my hub: 我的中心:

 [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();
    }
}

angular SignalR service: 角度SignalR服务:

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

I want to get the user in my hub so i can map the users to the connection id's. 我想让用户进入我的中心,这样我就可以将用户映射到连接ID。

You're not showing your using statements and I see you are also using MVC. 您没有显示出using语句,但我看到您也在使用MVC。 Maybe you're using the wrong AuthorizeAttribute? 也许您使用的是错误的AuthorizeAttribute?

Make sure you are using Microsoft.AspNet.SignalR.AuthorizeAttribute and not the MVC one. 确保您使用的是Microsoft.AspNet.SignalR.AuthorizeAttribute而不是MVC。

The problem with SignalR is that it cannot modify the header to send the token so SignalR的问题在于它无法修改标头以发送令牌,因此

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

does not work with SignalR as the token is expected in the URL. 不适用于SignalR,因为URL中应包含令牌。

The following however works with both Authenticated API calls and Authenticated SignalR connections 但是,以下内容可用于Authenticated API调用和Authenticated 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;
    }
};

}); });

You can test this in your hub 您可以在集线器中对此进行测试

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

Both [Authorize] attributes for API and SignalR come from API和SignalR的[Authorize]属性都来自

using Microsoft.AspNetCore.Authorization;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM