ASP.NET SignalR使用JWT授权时出现401 Unauthorized错误问题求助
问题根因与解决方案
核心问题1:SignalR查询参数中Token的参数名错误
WebSocket协议不支持自定义请求头,所以SignalR客户端的accessTokenFactory返回的token会默认放到URL查询参数中,参数名为access_token,而你当前服务端OnMessageReceived事件中读取的是查询参数的authorization字段,自然取不到token导致401。
核心问题2:请求头中的Authorization带Bearer前缀未处理
如果你从Header读取Authorization值,默认格式是Bearer <token>,直接赋值给ctx.Token会把Bearer 前缀也带入验证逻辑,导致token格式错误。
其他兼容/配置问题
- 客户端
@microsoft/signalr@5.x和服务端Microsoft.AspNetCore.SignalR@1.x跨大版本存在兼容性风险,建议服务端升级到对应.NET Core 3.1+版本,或者客户端降级到1.x版本对齐。 - CORS配置中存在拼写错误:
WithOrigins("http://locahost:4000")里的locahost少了字母l,正确应为localhost。
修复步骤
- 调整服务端
OnMessageReceived事件中的token读取逻辑,示例修改如下:
OnMessageReceived = ctx => { Log.Logger.Information("Authentication - Message received."); var path = ctx.HttpContext.Request.Path; if (!path.StartsWithSegments("/apphub", StringComparison.OrdinalIgnoreCase)) { return Task.CompletedTask; } // 优先读取SignalR默认的access_token查询参数 if (ctx.Request.Query.TryGetValue("access_token", out var queryToken)) { ctx.Token = queryToken; return Task.CompletedTask; } // 读取Header的话需要移除Bearer前缀 if (ctx.Request.Headers.TryGetValue("Authorization", out var headerToken)) { var token = headerToken.ToString().Replace("Bearer ", string.Empty); if (!string.IsNullOrEmpty(token)) { ctx.Token = token; } } return Task.CompletedTask; }
- 修正CORS配置中的域名拼写错误,本地调试可以直接用
AllowAnyOrigin配合AllowCredentials即可。 - 对齐客户端和服务端的SignalR主版本,避免跨版本兼容问题。
- 确认服务端中间件顺序正确:必须先调用
UseAuthentication,再调用UseAuthorization,最后调用UseEndpoints/UseSignalR。
内容的提问来源于stack exchange,提问作者user1563232
相关产品推荐
相关产品推荐

