Bru*_*lin 8 c# jwt signalr asp.net-core
我有一个 REST API(核心 2.1),它需要支持 SPA,使用 SignalR 提供安静的端点和一些实时交互功能;
Hub/MVC 路由在同一台服务器上运行,该服务器也是 JWT 令牌的提供者。
登录后,客户端会收到一个 JWT 令牌,该令牌放置在每个 REST 请求的标头上,否则会收到 401(这是与[Authorize]属性一起使用的)。
在客户端,下面的代码尝试连接到我的 /hub 端点:
new HubConnectionBuilder().withUrl(HUB_URL, { accessTokenFactory: () => this.getToken() })
如果我放置[Authorize]在我的 Hub 类中,我会收到以下错误(未经授权,客户端可以正确发送和收听):
WebSocket 连接到 'wss://localhost:5001/hub?id=MY_ID&access_token=MY_TOKEN' 失败:HTTP 身份验证失败;没有可用的有效凭据
服务器记录了失败的身份验证:
(在 AddJwtBearerOptions.Events.OnMessageReceived 上触发 console.log)
信息:Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
请求开始 HTTP/1.1 GET https://localhost:5001/hub?id=MY_ID&access_token=MY_TOKEN
信息:Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
授权失败。
信息:Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[12]
AuthenticationScheme:Bearer 受到挑战。
信息:Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
请求在 0.3658ms 401 内完成
与那些请求不同的是,使用 SAME JWT TOKEN 和 REST 令牌(使用[Authorize]),使用Header: Bearer XXXX而不是查询字符串,触发OnTokenValidated. 将OnAuthenticationFailed永远不会触发,即使验证失败:
(在 AddJwtBearerOptions.Events.OnMessageReceived 上触发了 console.log)
信息:Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
请求开始 HTTP/1.1 GET https://localhost:5001/api/products application/json
(触发了一个console.log on AddJwtBearerOptions.Events.OnTokenValidated)
info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[2]
成功验证令牌。
ConfigureServices(IServiceCollection)
services.AddSignalR();
services.AddCors(option => option.AddPolicy("CorsPolicy", p => p.AllowAnyHeader().AllowAnyOrigin().AllowAnyMethod().AllowCredentials()));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options => {
options.TokenValidationParameters = new TokenValidationParameters{
ValidateIssuer = true,
ValidIssuer = Configuration["JWT:Issuer"],
ValidateLifetime = true,
ValidateAudience = false,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JWT:SecurityKey"]))
};
});
Run Code Online (Sandbox Code Playgroud)
Configure(IApplicationBuilder)
app.UseAuthentication();
app.UseCors("CorsPolicy");
app.UseHttpsRedirection();
app.UseMvc();
app.UseSignalR(routes => {
routes.MapHub<ApplicationHub>("/hub");
});
Run Code Online (Sandbox Code Playgroud)
您还需要在该.AddJwtBearer部分中添加此块:
// 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.
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("/hub")))
{
// Read the token out of the query string
context.Token = accessToken;
}
return Task.CompletedTask;
}
};
Run Code Online (Sandbox Code Playgroud)
这可以在文档中找到。
信息:Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2] 授权失败。信息:Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[12] AuthenticationScheme:Bearer 受到挑战。信息:Microsoft.AspNetCore.Hosting.Internal.WebHost[2] 请求在 0.3658ms 401 内完成
花费 20 小时进行修复。:( 原因在:
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public class ChatHub : Hub<IChatClient>
Run Code Online (Sandbox Code Playgroud)
我的服务配置:
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options => ...)
Run Code Online (Sandbox Code Playgroud)
UPD:此处为 JS 客户端的完整工作示例。
| 归档时间: |
|
| 查看次数: |
7001 次 |
| 最近记录: |