【问题标题】:SignalR JWT claims missing in IUserIdProvider. JWT bearer OnMessageReceived not firingIUserIdProvider 中缺少 SignalR JWT 声明。 JWT 不记名 OnMessageReceived 未触发
【发布时间】:2019-04-30 10:11:10
【问题描述】:

我正在尝试使用 .NET 客户端和服务器设置 SignalR。

我只需要一种自定义方法来提供已连接客户端的 ID,而且似乎唯一的方法是在实现 IUserIdProvider 接口时填充作为 HubConnectionContext 参数一部分的声明。

在我的客户端上,我正在构建一个按预期工作的 JWT(验证它的构建是否正确)。

在我的服务器上,我已按照here提供的确切说明进行操作

但是,OnMessageReceived 回调不会触发,因此令牌被忽略,随后 IUserIdProvider 中的声明数组为空。

值得注意的是,IUserIdProvider 在客户端连接时仍然会被调用。

这是我的客户端 JWT 生成代码:

        _hubConnection = new HubConnectionBuilder()
            .WithUrl($"{_hubUrl}", options => options.AccessTokenProvider = () =>
            {
                var jwtHandler = new JwtSecurityTokenHandler();
                var credentials = new SigningCredentials(_securityKey, SecurityAlgorithms.HmacSha256);
                var jwt = new JwtSecurityToken(claims: new[] { new Claim("Id", _id) }, signingCredentials: credentials);
                var tokenString = jwtHandler.WriteToken(jwt);
                return Task.FromResult(tokenString);
            })
            .Build();

这是我的启动配置服务功能:

public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<IUserIdProvider, MyIdProvider>();

        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        }).AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                LifetimeValidator = (before, expires, token, param) =>
                {
                    return true;
                },
                ValidateAudience = false,
                ValidateIssuer = false,
                ValidateActor = false,
                ValidateLifetime = true,
                IssuerSigningKey = SecurityKey
            };
            options.Events = new JwtBearerEvents
            {
                OnMessageReceived = context =>
                {
                    // breakpoints never hit...
                    var accessToken = context.Request.Query["access_token"];
                    var path = context.HttpContext.Request.Path;
                    if (!string.IsNullOrWhiteSpace(accessToken) &&
                        path.StartsWithSegments("myHub"))
                    {
                        context.Token = accessToken;
                    }
                    return Task.CompletedTask;
                }
            };
        });

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        services.AddSignalR();
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc(Version, new OpenApiInfo
            {
                Version = Version,
                Title = Name
            });
        });            
    }

最后是我的 IUserIdProvider 实现:

    public class MyIdProvider : IUserIdProvider
{
    public string GetUserId(HubConnectionContext connection)
    {
        var id = connection.User.Claims.First(x => x.Type == "Id").Value;
        return id;
    }
}

提前致谢。

【问题讨论】:

  • 你检查过是不是CORS问题吗?
  • 试过让一切都无济于事。

标签: c# asp.net-core jwt signalr


【解决方案1】:

我必须解决几个问题才能使其正常工作。

首先,Hub 需要 [Authorize] 属性,否则永远不会调用 OnMessageReceived。

其次,我错过了管道正常运行所需的 app.UseAuthentication()。

进行这些更改后,我的声明得到了正确处理。

【讨论】:

    猜你喜欢
    • 2021-08-06
    • 2019-07-18
    • 1970-01-01
    • 2017-09-09
    • 1970-01-01
    • 2021-04-21
    • 2023-02-03
    • 2020-02-21
    • 1970-01-01
    相关资源
    最近更新 更多