.NET SignalR携带JWT无法连接问题求助
问题现象
使用.NET Core 3.1生成的JWT Token连接.NET 6的SignalR Hub时,Token已通过access_token参数发送,但服务端拒绝认证,WebSocket连接失败,错误信息如下:
错误: 启动连接失败: 错误: WebSocket连接失败。服务器上找不到该连接,可能端点不是SignalR端点、连接ID不存在,或代理阻止了WebSocket。若有多台服务器,请检查是否启用了粘性会话。
未捕获(承诺中)错误: WebSocket连接失败。服务器上找不到该连接,可能端点不是SignalR端点、连接ID不存在,或代理阻止了WebSocket。若有多台服务器,请检查是否启用了粘性会话。
WebSocket连接到'wss://localhost:60001/menushowhidehub?access_token=Bearer%20eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'失败:
信息: (WebSocket传输)传输出现错误。
代码问题排查与修复
1. JS端accessTokenFactory错误添加Bearer前缀
SignalR通过access_token参数传递Token时,不需要添加Bearer 前缀——JWT中间件会自动处理认证头格式,前缀会被当作Token的一部分导致验证失败。
修改前JS代码:
const connection = new signalR.HubConnectionBuilder() .withUrl("https://" + url + hubName, { accessTokenFactory: () => 'Bearer ' + accessToken, skipNegotiation: true, transport: signalR.HttpTransportType.WebSockets }) .withAutomaticReconnect() .build();
修改后:
const connection = new signalR.HubConnectionBuilder() .withUrl("https://" + url + hubName, { accessTokenFactory: () => accessToken, // 移除Bearer前缀 skipNegotiation: true, transport: signalR.HttpTransportType.WebSockets }) .withAutomaticReconnect() .build();
2. .NET 6端JWT配置冲突(Authority参数冗余)
已通过TokenValidationParameters指定了ValidIssuer和ValidAudience,额外添加options.Authority会触发OpenID Connect的issuer验证逻辑,与自定义JWT配置冲突,需移除该参数。
修改前Program.cs代码片段:
options.Authority = "https://localhost:5001/"; // 冗余配置,需删除
修改后:直接删除上述Authority配置行,保留TokenValidationParameters即可。
3. OnMessageReceived事件未限定SignalR路径范围
当前代码会对所有请求的access_token参数进行处理,可能干扰其他接口的认证逻辑,需限定仅处理SignalR Hub路径的请求。
修改前OnMessageReceived代码:
OnMessageReceived = context => { var accessToken = context.Request.Query["access_token"]; if (string.IsNullOrEmpty(accessToken) == false) { context.Token = accessToken; } return Task.CompletedTask; }
修改后:
OnMessageReceived = context => { // 仅处理SignalR Hub路径的请求 if (context.Request.Path.StartsWithSegments("/menushowhidehub") && !string.IsNullOrEmpty(context.Request.Query["access_token"])) { context.Token = context.Request.Query["access_token"]; } return Task.CompletedTask; }
4. 确认认证中间件的注册顺序
在Program.cs中,必须确保UseAuthentication()和UseAuthorization()的顺序正确,且位于UseRouting()之后、UseEndpoints()之前:
app.UseRouting(); // 认证授权必须在路由之后,端点之前 app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapHub<MenuShowHideHub>("/menushowhidehub"); // 其他端点配置 });
5. 验证Token本身的有效性
可以使用JWT解码工具检查Token的:
iss(签发者)是否与服务端ValidIssuer一致aud(受众)是否与服务端ValidAudience一致exp(过期时间)是否未过期- 签名密钥是否与服务端
SecurityKey完全匹配(注意大小写、特殊字符)
内容的提问来源于stack exchange,提问作者Batu han

