首页 > 解决方案 > 什么是默认的 Javascript SignalR 客户端身份验证方案?

问题描述

我的 SignalR 应用程序有两个客户端:用于 Web 浏览器的 Javascript 客户端和使用 JWT 承载身份验证的 Android 客户端 ( Gurgen/SignalR-.net-core-android-client )。

我将此属性添加到我的 SignalR Hub:

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme + "," + CookieAuthenticationDefaults.AuthenticationScheme)]
public class MyHub : Hub

还有我的Startup.cs文件:

        public void ConfigureServices(IServiceCollection services)
        {
        //…
        services.AddAuthentication()
            .AddCookie(cfg => cfg.SlidingExpiration = true)
            .AddJwtBearer(options =>
            {
                options.RequireHttpsMetadata = false;
                options.SaveToken = true;
                options.TokenValidationParameters = new TokenValidationParameters()
                {
                    ValidIssuer = Configuration["Tokens:Issuer"],
                    ValidAudience = Configuration["Tokens:Issuer"],
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Tokens:Key"]))
                };
            });
        services.AddSignalR();
        //…

Android 客户端使用标头身份验证承载令牌成功登录。但是Web 客户端无法连接到集线器(401 Unauthorized)。

当我删除 [Authorize] 属性时,javascript 客户端工作!

什么是默认的 Javascript SignalR 客户端身份验证方案?或者我提出了什么问题?

我使用 dotnet core 2.1、Microsoft.AspNetCore.SignalR,我的 IDE 是 Visual Studio for Mac。

标签: asp.net-core-signalr

解决方案


这是来自SignalR 文档

在标准 Web API 中,不记名令牌在 HTTP 标头中发送。但是,在使用某些传输时,SignalR 无法在浏览器中设置这些标头。使用 WebSockets 和服务器发送事件时,令牌作为查询字符串参数传输。

services.AddAuthentication(options =>
        {
            // ...
        })
        .AddJwtBearer(options =>
        {
            // ...

            // We have to hook the OnMessageReceived event in order to
            // allow the JWT authentication handler to read the access
            // token from the query string when a WebSocket or 
            // Server-Sent Events request comes in.

            // Sending the access token in the query string is required due to
            // a limitation in Browser APIs. We restrict it to only calls to the
            // SignalR hub in this code.
            // See https://docs.microsoft.com/aspnet/core/signalr/security#access-token-logging
            // for more information about security considerations when using
            // the query string to transmit the access token.
            options.Events = new JwtBearerEvents
            {
                OnMessageReceived = context =>
                {
                    var accessToken = context.Request.Query["access_token"];

                    // If the request is for our hub...
                    var path = context.HttpContext.Request.Path;
                    if (!string.IsNullOrEmpty(accessToken) &&
                        (path.StartsWithSegments("/hubs/chat")))
                    {
                        // Read the token out of the query string
                        context.Token = accessToken;
                    }
                    return Task.CompletedTask;
                }
            };
        });

推荐阅读