我正在使用使用 JWT 的 asp.net core 实现一个 web api。我正在努力学习,但没有使用第三方解决方案,例如 IdentityServer4。
我已经让 JWT 配置正常工作,但我对如何在 JWT 过期时实现刷新 token 感到困惑。
下面是我在 startup.cs 中的 Configure 方法中的一些示例代码。
app.UseJwtBearerAuthentication(new JwtBearerOptions()
{
AuthenticationScheme = "Jwt",
AutomaticAuthenticate = true,
AutomaticChallenge = true,
TokenValidationParameters = new TokenValidationParameters()
{
ValidAudience = Configuration["Tokens:Audience"],
ValidIssuer = Configuration["Tokens:Issuer"],
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Tokens:Key"])),
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
}
});
下面是用于生成 JWT 的 Controller 方法。出于测试目的,我已将到期时间设置为 30 秒。
[Route("Token")]
[HttpPost]
public async Task<IActionResult> CreateToken([FromBody] CredentialViewModel model)
{
try
{
var user = await _userManager.FindByNameAsync(model.Username);
if (user != null)
{
if (_hasher.VerifyHashedPassword(user, user.PasswordHash, model.Password) == PasswordVerificationResult.Success)
{
var userClaims = await _userManager.GetClaimsAsync(user);
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, user.UserName),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
}.Union(userClaims);
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwt.Key));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: _jwt.Issuer,
audience: _jwt.Audience,
claims: claims,
expires: DateTime.UtcNow.AddSeconds(30),
signingCredentials: creds
);
return Ok(new
{
access_token = new JwtSecurityTokenHandler().WriteToken(token),
expiration = token.ValidTo
});
}
}
}
catch (Exception)
{
}
return BadRequest("Failed to generate token.");
}
非常感谢一些指导。
最佳答案
首先,您需要生成一个刷新 token 并将其保存在某处。这是因为您希望能够在需要时使它无效。如果您要遵循与访问 token 相同的模式 - 所有数据都包含在 token 中 - 最终落入坏人之手的 token 可用于在刷新 token 的生命周期内生成新的访问 token ,这可能会很长时间。
那么你到底需要坚持什么?
您需要某种不容易猜到的唯一标识符,GUID 就可以了。您还需要数据才能颁发新的访问 token ,很可能是用户名。有了用户名,您就可以跳过 VerifyHashedPassword(...) 部分,但对于其余部分,只需遵循相同的逻辑即可。
要获得刷新 token ,您通常使用范围“offline_access”,这是您在发出 token 请求时在模型 (CredentialViewModel) 中提供的内容。与普通的访问 token 请求不同,您不需要提供用户名和密码,而是刷新 token 。当收到带有刷新 token 的请求时,您会查找持久标识符并为找到的用户颁发 token 。
以下是快乐路径的伪代码:
[Route("Token")]
[HttpPost]
public async Task<IActionResult> CreateToken([FromBody] CredentialViewModel model)
{
if (model.GrantType is "refresh_token")
{
// Lookup which user is tied to model.RefreshToken
// Generate access token from the username (no password check required)
// Return the token (access + expiration)
}
else if (model.GrantType is "password")
{
if (model.Scopes contains "offline_access")
{
// Generate access token
// Generate refresh token (random GUID + model.username)
// Persist refresh token
// Return the complete token (access + refresh + expiration)
}
else
{
// Generate access token
// Return the token (access + expiration)
}
}
}
关于c# - 如何在 asp.net 核心 web api(无第 3 方)中实现 JWT 刷新 token ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43467290/