我们能在Asp.NET Core中销毁/使JWT令牌失效吗?

26

我使用ASP.NET Core和ASP.NET Core Identity生成JWT令牌。

在客户端,我的React(SPA)应用程序调用API创建令牌,然后在子请求中包括Authorization: Bearer 来自API的令牌

当我想要注销时,如何立即使令牌在服务器端失效?

目前,我只是在客户端删除了bear令牌,并不包含在下一个请求中。

参考:https://blogs.msdn.microsoft.com/webdev/2017/04/06/jwt-validation-and-authorization-in-asp-net-core/


Startup.cs文件中的Configure部分代码:

app.UseJwtBearerAuthentication(new JwtBearerOptions
{
    AutomaticAuthenticate = true,
    AutomaticChallenge = true,
    TokenValidationParameters = new TokenValidationParameters
    {
        ValidIssuer = "MySite",
        ValidAudience = "MySite",
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("VERYL0NGKEYV@LUETH@TISSECURE")),
        ValidateLifetime = true
    }
});

创建令牌的API

[HttpPost("Token")]
public async Task<IActionResult> CreateToken([FromBody] LoginModel model)
{
    try
    {
        var user = await userManager.FindByNameAsync(model.Email);
        if (passwordHasher.VerifyHashedPassword(user, user.PasswordHash, model.Password) == PasswordVerificationResult.Success)
        {

            var claims = new[]
            {
                new Claim(JwtRegisteredClaimNames.Sub, user.UserName),
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                new Claim(JwtRegisteredClaimNames.Email, user.Email)
            };

            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("VERYL0NGKEYV@LUETH@TISSECURE"));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            var token = new JwtSecurityToken(
                "MySite",
                "MySite",
                claims,
                expires: DateTime.UtcNow.AddMinutes(45),
                signingCredentials: creds);

            return Ok(new
            {
                Token = new JwtSecurityTokenHandler().WriteToken(token),
                Expiration = token.ValidTo,
            });
        }
        return BadRequest();
    }
    catch (Exception ex)
    {
        logger.LogError(ex.ToString());
        return StatusCode((int)HttpStatusCode.InternalServerError);
    }
}
1个回答

33

如果你想让它立刻失效,那么就需要几个步骤:

  1. 在创建token时缓存token的ID,其持续时间应该与token(访问token和刷新token)的过期时间一样长
  2. [如果是农场/多实例]你需要将它缓存在分布式缓存中,如Redis
  3. [如果是农场/多实例]你需要通过消息总线(例如使用Redis、RabbitMQ或Azure Message Bus)将其传播到应用程序的每个实例,以便它们可以将其存储在本地内存缓存中(这样每次验证时都不需要进行网络调用)
  4. 在授权期间,需要验证ID是否仍然存在于缓存中;如果不存在,则拒绝授权(401)
  5. 当用户注销时,需要从缓存中删除你的项目。
  6. [如果是农场/多实例]从分布式缓存中删除该项目,并向所有实例发送消息,以便它们可以将其从本地缓存中删除

其他解决方案不需要消息总线/可分布式缓存会要求每个请求都联系认证服务器,从而破坏了JWT token的主要优势。

JWT的主要优点是它们是自包含的,一个web服务不必调用另一个服务来验证它。可以通过验证签名(因为用户无法更改token而不使签名失效)和token的过期时间/受众来本地验证。

最好的方法是将访问令牌的时间设置得足够短(≤5分钟),刷新令牌则运行时间较长。

但是,如果要立即使其过期,就需要在不失去优势或使解决方案变得显着复杂的情况下进行一些操作。


有没有可以参考的样例? - Jeeva J
你不应该在公共客户端中使用刷新令牌。 - Carlos Jimenez Bermudez

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