.NET 7 Blazor WASM中SignalR为何未使用WebSocket通信?
问题:Blazor WASM SignalR 已建立WebSocket连接却仍使用长轮询通信
我有一个托管式.NET 7 Blazor WASM项目,已与宿主建立SignalR连接且通信正常。但发现尽管WebSocket连接已建立,通信仍采用long-poll + calls方式,连SSE都未使用。当前为开发环境,客户端与服务器同机运行,无WebSocket阻塞情况,且连接选项中已设置AccessTokenProvider。
请问这是为何?与开发环境或WASM有关吗?生产环境也会如此吗?
更新于23-12-27
按照建议添加了客户端日志,结果如下:
(顺带一提:浏览器是Edge……不支持SSE??)
展开的错误信息:
服务器端日志:
从日志来看,连接未被拒绝,仅受到质询。且实际WebSocket连接已携带所需令牌:
客户端代码:

服务器代码:




分析与解决
1. 核心原因:SSE传输因令牌问题失败触发降级
从客户端错误日志可见Failed to construct 'EventSource',Edge完全支持SSE,问题出在身份验证的传输限制:
- SSE受浏览器安全限制,无法在请求头中携带
AuthorizationBearer令牌,导致客户端尝试SSE连接时,因无有效令牌被服务器质询,最终SSE连接失败。 - SignalR的传输协商逻辑会在某一传输失败时自动降级到下一种可用方式,SSE失败后就降级到了长轮询;即便WebSocket连接本身能成功,协商阶段的失败已经触发了降级流程。
2. 与开发环境/WASM的关联
- 和开发环境本身无关,但本地身份验证配置(比如HTTPS、令牌传递逻辑)更容易暴露这类浏览器限制问题。
- WASM本身不限制WebSocket/SSE,问题根源是浏览器对SSE的请求头限制,和WASM runtime无关。
3. 生产环境的表现
如果不修复SSE的令牌传递问题,生产环境会出现同样的降级情况。可通过以下两种方式解决:
方案一:配置SSE通过查询字符串传递令牌
SSE支持从查询字符串读取令牌,需要同时修改客户端和服务器端:
- 客户端配置:确保SignalR为SSE传输启用查询字符串传令牌
hubConnection = new HubConnectionBuilder() .WithUrl(NavigationManager.ToAbsoluteUri("/chathub"), options => { options.AccessTokenProvider = async () => { var accessTokenResult = await AccessTokenProvider.RequestAccessToken(); accessTokenResult.TryGetToken(out var token); return token?.Value; }; // 显式指定允许的传输类型 options.Transports = HttpTransportType.WebSockets | HttpTransportType.ServerSentEvents | HttpTransportType.LongPolling; }) .Build();
- 服务器端配置:允许从查询字符串读取JWT令牌
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { // 保留原有TokenValidationParameters配置 options.Events = new JwtBearerEvents { OnMessageReceived = context => { var accessToken = context.Request.Query["access_token"]; var path = context.HttpContext.Request.Path; // 针对SignalR Hub路径,从查询字符串取令牌 if (!string.IsNullOrEmpty(accessToken) && path.StartsWithSegments("/chathub")) { context.Token = accessToken; } return Task.CompletedTask; } }; });
方案二:强制优先使用WebSocket
如果不需要兼容SSE/长轮询,可直接指定仅使用WebSocket传输,跳过降级逻辑:
options.Transports = HttpTransportType.WebSockets;
WebSocket支持在请求头携带Authorization令牌,不会出现SSE的限制问题,能稳定保持WebSocket连接。
内容的提问来源于stack exchange,提问作者ZorgoZ
相关产品推荐
相关产品推荐

