基于多租户的Asp.net Core网站中,基于参数的JWT身份验证

4

我正在使用基于JWT的身份验证来开发我的.NET Core 2.1网站。目前这个功能运行良好。现在,我需要将一个API设计成多租户,并且每个租户都有自己的密钥。租户ID将作为参数传递到API中。

        [Authorize]
        [HttpGet("tenant/{id}")]
        public async Task<IActionResult> GetInfo(string id)
        {
        }

每个租户都将签署JWT并添加到Authorization标头中。我无法想到一种根据参数更改IssuerSigningKey的方法。我尝试了以下两种方法:
1. 通过使API内部的JWT验证[AllowAonymus]来验证JWT。这可以工作,但最终我必须编写所有的JWT验证代码。 2. 实现ISecurityTokenValidator
我可以实现ISecurityTokenValidator来验证令牌,并在启动配置中使用它,类似于这样:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
            {
                options.SecurityTokenValidators.Clear();
                options.SecurityTokenValidators.Add(new JWTSecurityTokenValidator());
            });

我实现了自己的类来验证令牌。

public class JWTSecurityTokenValidator : ISecurityTokenValidator
{
    public ClaimsPrincipal ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken validatedToken)
    {
            // Implement the logic
    }
}

但是我又一次最终要做到很多工作量。而且,在ValidateToken中我无法访问参数“tenantId”。

3.使用IssuerSigningKeyResolver: 我可以实现一个委托:

IEnumerable<SecurityKey> IssuerSigningKeyResolver(string token, SecurityToken securityToken, string kid, TokenValidationParameters validationParameters)

我无法访问“tenantId”参数以选择适当的密钥。

是否有优雅的解决方案可以基于该参数选择IssuerSigningKey以便我不需要编写自己的逻辑来验证JWT?还是唯一的选择是使用第一个选项?

1个回答

5

你可以使用 DI 技术将 IHttpContextAccessor 实例传递给你的 JWTSecurityTokenValidator,并获取 IHttpContextAccessor.HttpContext 属性的值。

从 .Net Core 2.1 开始,你可以使用扩展方法进行注册:

services.AddHttpContextAccessor();

接着在您的自定义JWTSecurityTokenValidator中,修改以注入IHttpContextAccessor

private readonly IHttpContextAccessor _httpContextAccessor;

public JWTSecurityTokenValidator(IHttpContextAccessor httpContextAccessor) {
    _httpContextAccessor = httpContextAccessor;
}

修改Startup.cs中的注册:

options.SecurityTokenValidators.Clear();

options.SecurityTokenValidators.Add(new JWTSecurityTokenValidator(services.BuildServiceProvider().GetService<IHttpContextAccessor>()));

ValidateToken方法中,你可以从_httpContextAccessor.HttpContext读取参数,根据你传递参数的方式,可以从查询字符串或路径中读取:

public ClaimsPrincipal ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken validatedToken)
{
        var xx = _httpContextAccessor.HttpContext.Request;
        ........
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接