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

如何用IdentityServer4认证SignalR客户端?遇403/401错误求助

SignalR连接IdentityServer认证失败(403/401)排查

问题场景

我通过IdentityServer(地址http://localhost:5006)获取Token,客户端代码如下:

var httpClient = new HttpClient();
var discoveryDocument = httpClient.GetDiscoveryDocumentAsync("http://localhost:5006").Result;
var tokenResponse = httpClient.RequestClientCredentialsTokenAsync(
    new ClientCredentialsTokenRequest
    {
        Address = discoveryDocument.TokenEndpoint,
        ClientId = "client",
        ClientSecret = "Prevo100",
        Scope = "prevo100-api"
    }).Result;

尝试连接SignalR Hub(地址http://localhost:5119/Prevo100)时,调用StartAsync()抛出异常:

System.AggregateException : 'One or more errors occurred. (Response status code does not indicate success: 403 (Forbidden).)'

偶尔也会出现401错误。SignalR客户端连接代码:

var url = "http://localhost:5119/Prevo100";

HubConnection connection = new HubConnectionBuilder()
    .WithUrl(url, options =>
    {
        options.AccessTokenProvider = () => Task.FromResult(tokenResponse.AccessToken);
    })
    .WithAutomaticReconnect()
    .Build();

var client = new Prevo100WebClient(connection);

connection.StartAsync().Wait(); // <== 异常发生在此处

服务器端配置

SignalR Hub所在服务器的配置代码:

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication("Bearer")
        .AddJwtBearer("Bearer", options =>
        {
            options.Authority = "http://localhost:5006";
            options.RequireHttpsMetadata = false;

            options.Audience = "prevo100-api";

            options.TokenValidationParameters =
            new Microsoft.IdentityModel.Tokens.TokenValidationParameters
            {
                ValidateAudience = false
            };

            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("/Prevo100"))
                    {
                        context.Token = accessToken;
                    }
                    return Task.CompletedTask;
                }
            };
        });

    services.AddSignalR(hubOptions =>
    {
        //hubOptions.ClientTimeoutInterval // 30 secondes par défaut
    });
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseFileServer();
    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapHub<Prevo100Hub>("/Prevo100");
    });
}

Hub类添加了授权特性:

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public class Prevo100Hub : Hub<IPrevo100Client>, IHubContract
{
//....
}

请求帮忙排查认证失败导致的403/401错误原因。


排查步骤

1. 验证Token有效性

  • 先确认tokenResponse.IsError是否为false,如果是true,查看tokenResponse.Error字段获取具体错误
  • 将tokenResponse.AccessToken用JWT解析工具查看:
    • 确认iss字段为http://localhost:5006
    • 确认scope包含prevo100-api
    • 检查exp字段,确认Token未过期

2. 检查Token传递与提取逻辑

  • 在客户端连接前打印tokenResponse.AccessToken,确保不是空值或无效值
  • 在服务器的OnMessageReceived事件中添加日志,打印accessToken和path,确认是否能正确获取到Token

3. 修正认证配置冲突

服务器配置中同时设置了options.Audience = "prevo100-api"和ValidateAudience = false,二者冲突:

  • 若需验证Audience,删除ValidateAudience = false,确保Token的aud包含prevo100-api
  • 若无需验证Audience,删除options.Audience = "prevo100-api",避免冗余配置

4. 确认IdentityServer客户端配置

检查IdentityServer中client客户端的配置项:

  • 确保AllowedGrantTypes包含client_credentials
  • 确保AllowedScopes包含prevo100-api
  • 确保ClientSecrets中存在Prevo100(注意大小写和格式匹配)

5. 检查中间件与协议影响

  • 服务器启用了UseHttpsRedirection,但客户端用http连接,可能导致重定向时丢失Token,开发环境可临时注释该中间件测试
  • 确认SignalR使用的传输协议(WebSocket/SSE)是否触发了OnMessageReceived逻辑,可在日志中打印请求的传输类型

6. 隔离授权环节验证

  • 临时去掉Hub类的[Authorize]特性,测试是否能正常连接,以此确认是否是授权规则导致的问题
  • 若去掉后能连接,检查[Authorize]是否包含角色、声明等额外限制,确保Token中包含对应内容

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 05:07:31