SignalR Angular客户端连接.NET 8 Azure服务遇查询字符串过长404.15错误
SignalR查询字符串过长(404.15)问题解决方案
你不是唯一遇到这个问题的开发者
很多使用SignalR结合长JWT Bearer令牌的开发者都碰到过这类问题——浏览器(尤其是Edge/Chrome)和IIS对URL/查询字符串的长度限制,加上默认情况下SignalR浏览器客户端会把令牌放在查询字符串中传递,很容易触发404.15错误。
你当前操作的潜在问题
- 依赖查询字符串传递令牌:不仅会触发长度限制问题,还存在安全风险——令牌会被记录在服务器日志、浏览器历史记录和网络请求日志中,增加泄露风险。
- 未利用SignalR的Negotiate机制传递令牌:默认的查询串传令牌是 fallback 方案,其实可以通过Negotiate请求的Header传递令牌,从根源上规避长度限制。
通用简便解决方案
1. Angular(JS客户端)修改方案
放弃查询串传令牌,改为在Negotiate请求的Authorization Header中传递令牌,SignalR会基于Negotiate返回的连接ID建立后续WebSockets连接,无需再在URL中携带令牌:
import { HubConnectionBuilder, HttpTransportType } from '@microsoft/signalr'; // 替换为你的令牌和Hub地址 const authToken = 'your-msal-acquired-token'; const hubUrl = '/your-hub-endpoint'; const connection = new HubConnectionBuilder() .withUrl(hubUrl, { transport: HttpTransportType.WebSockets, // 配置HttpClient在Negotiate请求中添加Authorization Header configureHttpClient: (httpClient) => { httpClient.defaults.headers.common['Authorization'] = `Bearer ${authToken}`; }, skipNegotiation: false, // 必须开启Negotiate流程,才能传递Header }) .build();
2. Blazor客户端修改方案
通过自定义HttpMessageHandler在Negotiate请求中添加Authorization Header,避免令牌出现在查询字符串中:
using System.Net.Http; using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.SignalR.Client; var hubUrl = "your-hub-url"; var token = "your-acquired-token"; var hubConnection = new HubConnectionBuilder() .WithUrl(hubUrl, options => { options.CloseTimeout = TimeSpan.FromSeconds(120); options.Transports = HttpTransportType.WebSockets; // 配置消息处理器添加Authorization Header options.HttpMessageHandlerFactory = handler => new AuthHeaderHandler(handler, token); // 关闭默认的查询串令牌传递 options.AccessTokenProvider = null; }) .Build(); // 自定义DelegatingHandler用于添加Authorization Header public class AuthHeaderHandler : DelegatingHandler { private readonly string _bearerToken; public AuthHeaderHandler(HttpMessageHandler innerHandler, string bearerToken) : base(innerHandler) { _bearerToken = bearerToken; } protected override Task<HttpResponseMessage> SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { // 仅在Negotiate请求中添加Header if (request.RequestUri?.PathAndQuery.Contains("/negotiate") == true) { request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _bearerToken); } return base.SendAsync(request, cancellationToken); } }
如果是Blazor WebAssembly应用,还可以直接利用AuthorizationMessageHandler简化配置:
using Microsoft.AspNetCore.Components.WebAssembly.Authentication; var handler = new AuthorizationMessageHandler(); handler.ConfigureHandler( authorizedUrls: new[] { hubUrl }, scopes: new[] { "your-api-required-scope" }); var hubConnection = new HubConnectionBuilder() .WithUrl(hubUrl, options => { options.CloseTimeout = TimeSpan.FromSeconds(120); options.Transports = HttpTransportType.WebSockets; options.HttpMessageHandlerFactory = _ => handler; }) .Build();
3. 服务器端配套配置
保留你之前在web.config中设置的请求长度限制,以防SignalR fallback到ServerSentEvents或LongPolling等其他传输方式时触发长度问题:
<security> <requestFiltering> <requestLimits maxUrl="4096" maxQueryString="4096" /> </requestFiltering> </security>
内容的提问来源于stack exchange,提问作者fpdave100
相关产品推荐
相关产品推荐

