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

使用SignalR时持续遭遇401授权失败,求排查方案

解决SignalR + AAD JWT认证未授权问题

针对你遇到的Failed to invoke 'X' because user is unauthorized.错误,结合代码分析,问题主要集中在令牌传递格式和服务端令牌验证配置两方面,以下是具体修正方案:

1. 客户端令牌传递修正

你的客户端同时通过三种方式传递令牌(QueryString、AccessTokenProvider、Authorization Header),且令牌带了Bearer 前缀,这会导致服务端解析失败:

修正步骤:

  • 只保留一种令牌传递方式(推荐使用AccessTokenProvider,SignalR会自动适配WebSocket/SSE等不同传输协议)
  • 令牌常量仅存储纯JWT字符串,移除Bearer 前缀

修正后的客户端代码:

namespace HubTestClient
{
    using Microsoft.AspNetCore.SignalR.Client;

    public class MockClient
    {
        // 仅保留纯JWT,去掉"Bearer "前缀
        private const string Token = "<JWT from AAD>";

        private readonly HubConnection hubConnection;

        public MockClient()
        {
            this.hubConnection = new HubConnectionBuilder()
                .WithUrl("http://localhost:5110/Test", options =>
                {
                    // 仅通过AccessTokenProvider传递令牌,SignalR自动处理传输逻辑
                    options.AccessTokenProvider = () => Task.FromResult(Token);
                    // 移除冗余的Header和QueryString令牌传递,避免冲突
                })
                .Build();

            this.hubConnection.On<string>("ReceiveMessage", (message) =>
            {
                Console.WriteLine($"Received message: '{message}'");
            });
        }

        // 剩余代码保持不变...
    }
}

2. 服务端令牌验证配置修正

你的TokenValidationParameters配置过于宽松,关闭了签名验证,导致AAD令牌无法被正确校验:

修正步骤:

  • 开启签名验证(ValidateIssuerSigningKey默认值为true,可直接删除该配置项)
  • 配置正确的ValidIssuer和ValidAudience(从AAD应用注册信息中获取)
  • 确保Authority替换为实际租户ID

修正后的Program.cs中JWT配置部分:

builder.Services
    .AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(options =>
    {
        // 替换为你的实际租户ID,v2版本结尾加/v2.0,v1版本不加
        options.Authority = "https://login.microsoftonline.com/{YourTenantId}/v2.0";

        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            // 对应AAD的Issuer地址,与Authority匹配
            ValidIssuer = "https://login.microsoftonline.com/{YourTenantId}/v2.0",
            ValidateLifetime = true,
            ValidateAudience = true,
            // 替换为你的AAD应用注册Client ID
            ValidAudience = "{YourApplicationClientId}",
            // 保留默认签名验证,可删除该行
            ValidateIssuerSigningKey = true,
        };

        options.Events = new JwtBearerEvents
        {
            OnMessageReceived = context =>
            {
                var accessToken = context.Request.Query["access_token"];
                var path = context.HttpContext.Request.Path;
                
                if (!string.IsNullOrEmpty(accessToken) && path.StartsWithSegments("/Test"))
                {
                    context.Token = accessToken;
                }
                return Task.CompletedTask;
            }
        };
    });

3. 额外检查项

  • HTTPS重定向问题:服务端启用了UseHttpsRedirection,但客户端使用HTTP连接,重定向过程中可能丢失令牌。开发环境可临时注释app.UseHttpsRedirection();,或客户端改用HTTPS地址连接。
  • Hub授权简化:若已设置默认认证Scheme为JWT,可直接在Hub类上添加[Authorize],无需在方法上重复指定Scheme:
    [Authorize]
    internal class SimpleHub : Hub<ISimpleClient>
    {
        public async Task EchoMessage(string message) => await Clients.All.ReceiveMessage(message);
    }
    

验证步骤

  1. 使用JWT解析工具验证令牌未过期、签名有效,且aud(受众)与服务端ValidAudience一致
  2. 重启服务端和客户端,测试调用是否正常

内容的提问来源于stack exchange,提问作者Michael Butler

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 06:09:19