SignalR JWT声称在IUserIdProvider中丢失了。 JWT持票人OnMessageReceived没有解雇

问题描述 投票:1回答:1

我正在尝试使用.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();

这是我的Startup ConfigureServices函数:

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;
    }
}

提前致谢。

c# asp.net-core jwt signalr
1个回答
0
投票

为了实现这个目标,我必须解决几个问题。

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

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

进行这些更改后,我的声明正确地发生了。

© www.soinside.com 2019 - 2024. All rights reserved.