多租户Asp.net Core网站中基于参数的JWT认证

Ame*_*mey 4 c# multi-tenant jwt asp.net-core

我在 .net core 2.1 网站中使用基于 JWT 的身份验证。目前这工作正常。现在,我必须创建一个 API 多租户,并且每个租户都将拥有自己的密钥。租户 ID 将作为参数传递给 API。

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

每个租户都会签署 JWT 并添加到授权标头。我无法想出一种根据参数更改 IssuerSigningKey 的方法。我尝试了以下操作:

  1. 通过将其设为 [ ] 来验证 API 内的 JWT AllowAonymus。这可行,但我最终编写了所有 JWT 验证代码。

  2. 实施ISecurityTokenValidator

我可以实现ISecurityTokenValidator验证令牌并在启动配置中使用它,如下所示:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
            {
                options.SecurityTokenValidators.Clear();
                options.SecurityTokenValidators.Add(new JWTSecurityTokenValidator());
            });
Run Code Online (Sandbox Code Playgroud)

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

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

但我最终还是做了繁重的工作。另外,我无法访问 ValidateToken 中的参数“tenantId”。

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

IEnumerable<SecurityKey> IssuerSigningKeyResolver(string token, SecurityToken securityToken, string kid, TokenValidationParameters validationParameters)
Run Code Online (Sandbox Code Playgroud)

同样,我无法访问“tenantId”参数来选择适当的密钥。

是否有优雅的解决方案可以IssuerSigningKey根据参数进行选择,这样我就不需要编写自己的逻辑来验证 JWT?或者唯一的选择是选择第一个选项?

Nan*_* Yu 5

您可以使用 DI 将IHttpContextAccessor实例传递到您的实例JWTSecurityTokenValidator并获取属性值IHttpContextAccessor.HttpContext

从 .Net Core 2.1 开始,您可以使用扩展名进行注册:

services.AddHttpContextAccessor();
Run Code Online (Sandbox Code Playgroud)

然后在您的自定义中JWTSecurityTokenValidator,修改以注入IHttpContextAccessor

private readonly IHttpContextAccessor _httpContextAccessor;

public JWTSecurityTokenValidator(IHttpContextAccessor httpContextAccessor) {
    _httpContextAccessor = httpContextAccessor;
}
Run Code Online (Sandbox Code Playgroud)

修改注册Startup.cs

options.SecurityTokenValidators.Clear();

options.SecurityTokenValidators.Add(new JWTSecurityTokenValidator(services.BuildServiceProvider().GetService<IHttpContextAccessor>()));
Run Code Online (Sandbox Code Playgroud)

这样在ValidateToken方法中,您可以从以下位置读取参数_httpContextAccessor.HttpContext,根据您传递参数的方式,从查询字符串或路径中读取:

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