You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET SignalR携带JWT无法连接问题求助

SignalR WebSocket连接失败排查(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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 03:53:23