asp.net-core-signalr - 什么是默认的 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。
解决方案
这是来自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;
}
};
});
推荐阅读
- python - 为什么 LightGBM 中的 R2 分数为零?
- c - 为什么 Keil 在为 STM32F407 定义全局变量时向我显示警告
- .net - F# MailboxProcessor 异步混乱的打印语句
- html - 关于缺少 CSS 规则的警告?
- python - 初学者 Python:如何在我的代码中修复此函数检查,以便它循环返回以允许玩家选择
- tableau-api - Tableau Ask Data 服务将无法启动并且无法找到日志文件位置
- arrays - 如何映射存储在不是来自 api 的反应组件中的 json 对象?
- java - NoSuchElementException 在特定网页上带有无头 chrome 和 selenium
- javascript - Range addEventListner Input 更新太频繁
- java - 如何使用 Spring Webflux Reactive Java 将多个 Mono 映射到一个对象中?