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

连接SignalR Hub时HandleAuthenticateAsync多次调用,HTTP请求仅调用1次

问题原因

  1. SignalR 原生协商机制导致多请求触发认证
    SignalR 建立连接前默认会先发送negotiate协商请求获取可用传输协议、连接ID等信息,该请求会触发一次认证;协商成功后会发起实际传输协议(如WebSocket)的握手请求,再次触发认证,因此.NET客户端默认会出现2次认证调用。
    非.NET客户端(如浏览器端JS客户端)跨域访问时,协商请求前会先发送CORS OPTIONS预检请求,该请求也会触发认证逻辑,最终形成OPTIONS预检 → negotiate协商 → 传输握手3次请求,对应3次认证调用。
  2. 中间件配置错误放大问题
    你当前的中间件顺序存在两处错误:
  • UseAuthentication放在了UseRouting之前,认证中间件会在路由匹配前执行,所有请求无论是否匹配到SignalR/接口路由都会触发认证
  • 重复调用UseEndpoints,会导致路由匹配逻辑重复执行,进一步增加不必要的认证调用

解决方法

第一步:修正中间件配置

调整中间件顺序为ASP.NET Core官方推荐顺序,合并UseEndpoints调用:

app.UseCors(builder => builder
       .AllowAnyOrigin()
       .AllowAnyHeader()
       .AllowAnyMethod()
   );

// 先执行路由匹配,再处理认证
app.UseRouting();

app.UseAuthentication();
// 若有授权中间件需放在认证之后
// app.UseAuthorization();

// 合并端点映射,不要分开调用
app.UseEndpoints(endpoints => 
{
    endpoints.MapHub<MasterHub>("/connect");
    endpoints.MapControllers();
});

第二步:跳过OPTIONS预检请求的认证

在FbigAuthenticationHandler的HandleAuthenticateAsync方法开头增加预检请求跳过逻辑:

protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
    // 直接跳过CORS预检请求的认证校验
    if (Request.Method == HttpMethods.Options)
    {
        return AuthenticateResult.NoResult();
    }

    // 原有认证逻辑保留
    // ...
}

第三步(可选):关闭协商阶段进一步减少调用

如果确认所有客户端都仅使用WebSocket传输协议,可以在客户端配置关闭协商,仅保留一次WebSocket握手请求的认证:
.NET客户端配置示例:

var hubConnection = new HubConnectionBuilder()
    .WithUrl("你的Hub连接地址", options =>
    {
        // 仅当固定使用WebSocket时可开启
        options.SkipNegotiation = true;
        options.Transports = HttpTransportType.WebSockets;
        // 其余认证配置保留
    })
    .Build();

内容的提问来源于stack exchange,提问作者Adam Q

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 05:57:02