我们可以在 Asp.NET Core 中 destroy/invalidate JWT 令牌吗?
Could we destroy/invalidate JWT token in Asp.NET Core?
我使用 ASP.NET Core & ASP.NET core Identity 来生成 JWT 令牌。
在客户端,我的 React (SPA) 应用程序调用 API 来创建令牌,然后在子请求中包含 Authorization: Bearer
token from API
。
当我想登出时,如何立即在服务器端使令牌失效?
目前,我只是在客户端删除了 bear
令牌,而不包括在下一个请求中?
参考:https://blogs.msdn.microsoft.com/webdev/2017/04/06/jwt-validation-and-authorization-in-asp-net-core/
Configure
部分中的代码 Startup.cs
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);
}
}
您不能轻易让它过期,w/o 会失去它的一些优势或使解决方案变得更加复杂。
最好的办法是让访问令牌时间足够短(<= 5 分钟),刷新令牌时间足够长 运行。
但是如果你真的想立即使它失效,你需要做一些事情:
- 创建令牌后缓存令牌的 ID,持续时间与令牌(访问和刷新令牌)的到期时间一样长
- [如果Farm/multiple个实例]需要缓存在分布式缓存中,比如redis
- [If Farm/multiple instances]您需要通过消息总线(即使用 Redis、RabbitMQ 或 Azure 消息总线)将其传播到应用程序的每个实例,以便它们可以将其存储在本地内存缓存中(这样就不用网络调用了,每次都要验证)
- 授权时需要验证ID是否还在缓存中;如果不是,拒绝授权 (401)
- 当用户注销时,您需要从缓存中删除您的项目。
- [If Farm/multiple instances]从分布式缓存中删除项目并向所有实例发送消息,以便它们可以将其从本地缓存中删除
不需要消息 bus/distributable 缓存的其他解决方案将需要在每次请求时联系 auth 服务器,从而扼杀了 JWT 令牌的主要优势。
JWT 的主要优点是它们是独立的,Web 服务不必调用其他服务来验证它。可以通过验证签名(因为用户无法更改令牌 w/o 使签名无效)和令牌的到期时间 time/audience 来在本地验证它。
我使用 ASP.NET Core & ASP.NET core Identity 来生成 JWT 令牌。
在客户端,我的 React (SPA) 应用程序调用 API 来创建令牌,然后在子请求中包含 Authorization: Bearer
token from API
。
当我想登出时,如何立即在服务器端使令牌失效?
目前,我只是在客户端删除了 bear
令牌,而不包括在下一个请求中?
参考:https://blogs.msdn.microsoft.com/webdev/2017/04/06/jwt-validation-and-authorization-in-asp-net-core/
Configure
部分中的代码 Startup.cs
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);
}
}
您不能轻易让它过期,w/o 会失去它的一些优势或使解决方案变得更加复杂。
最好的办法是让访问令牌时间足够短(<= 5 分钟),刷新令牌时间足够长 运行。
但是如果你真的想立即使它失效,你需要做一些事情:
- 创建令牌后缓存令牌的 ID,持续时间与令牌(访问和刷新令牌)的到期时间一样长
- [如果Farm/multiple个实例]需要缓存在分布式缓存中,比如redis
- [If Farm/multiple instances]您需要通过消息总线(即使用 Redis、RabbitMQ 或 Azure 消息总线)将其传播到应用程序的每个实例,以便它们可以将其存储在本地内存缓存中(这样就不用网络调用了,每次都要验证)
- 授权时需要验证ID是否还在缓存中;如果不是,拒绝授权 (401)
- 当用户注销时,您需要从缓存中删除您的项目。
- [If Farm/multiple instances]从分布式缓存中删除项目并向所有实例发送消息,以便它们可以将其从本地缓存中删除
不需要消息 bus/distributable 缓存的其他解决方案将需要在每次请求时联系 auth 服务器,从而扼杀了 JWT 令牌的主要优势。
JWT 的主要优点是它们是独立的,Web 服务不必调用其他服务来验证它。可以通过验证签名(因为用户无法更改令牌 w/o 使签名无效)和令牌的到期时间 time/audience 来在本地验证它。