步骤
1、TokenModel.cs
DTO文件夹下新建TokenModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CitiesManager.Core.DTO
{
public class TokenModel
{
public string? Token { get; set; }
public string? RefreshToken { get; set; }
}
}
2、IJwtService.cs
添加一个方法GetPrincipalFromJwtToken
using CitiesManager.Core.DTO;
using CitiesManager.Core.Identity;
using System;
using System.Security.Claims;
namespace CitiesManager.Core.ServiceContracts
{
public interface IJwtService
{
AuthenticationResponse CreateJwtToken(ApplicationUser user);
ClaimsPrincipal? GetPrincipalFromJwtToken(string? token);
}
}
3、JwtService.cs
实现新方法
public ClaimsPrincipal? GetPrincipalFromJwtToken(string? token)
{
var tokenValidationParameters = new TokenValidationParameters()
{
ValidateAudience = true,
ValidAudience = _configuration["Jwt:Audience"],
ValidateIssuer = true,
ValidIssuer = _configuration["Jwt:Issuer"],
ValidateLifetime = false,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]))
};
JwtSecurityTokenHandler jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
ClaimsPrincipal principal = jwtSecurityTokenHandler.ValidateToken(token, tokenValidationParameters, out SecurityToken securityToken);
if (securityToken is not JwtSecurityToken jwtSecurityToken || !jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256,StringComparison.InvariantCultureIgnoreCase))
{
throw new SecurityTokenException("Invalid token");
}
return principal;
}
4、AccountController.cs
添加方法GenerateNewAccessToken生成新的Token
[HttpPost("generate-new-jwt-token")]
public async Task<IActionResult> GenerateNewAccessToken(TokenModel tokenModel)
{
if (tokenModel == null)
{
return BadRequest("Invalid client request");
}
ClaimsPrincipal? principal = _jwtService.GetPrincipalFromJwtToken(tokenModel.Token);
if (principal == null)
{
return BadRequest("Invalid jwt access token");
}
string? email = principal.FindFirstValue(ClaimTypes.Email);
ApplicationUser? user = await _userManager.FindByEmailAsync(email);
if (user == null || user.RefreshToken != tokenModel.RefreshToken || user.RefreshTokenExpirationDateTime <= DateTime.Now)
{
return BadRequest("Invalid refresh token");
}
AuthenticationResponse authenticationResponse = _jwtService.CreateJwtToken(user);
user.RefreshToken = authenticationResponse.RefreshToken;
user.RefreshTokenExpirationDateTime = authenticationResponse.RefreshTokenExpirationDateTime;
await _userManager.UpdateAsync(user);
return Ok(authenticationResponse);
}
5、account.service.ts
添加如下方法
public postGenerateNewToken(): Observable<any> {
var token = localStorage["token"];
var refreshToken = localStorage["refreshToken"]
return this.httpClient.post<any>(`${API_BASE_URL}generate-new-jwt-token`, {token: token, refreshToken: refreshToken});
}
6、cities.component.ts
添加如下方法
//Executes when the 'Refresh' button is clicked
refreshClicked(): void {
this.accountService.postGenerateNewToken().subscribe({
next: (response: any) => {
localStorage["token"] = response.token;
localStorage["refreshToken"] = response.refreshToken;
this.loadCities();
},
error: (error: any) => {
console.log(error);
},
complete: () => { },
})
}
7、cities.component.html
添加Refresh按钮
<button type="button" class="button button-blue-back mt" (click)="refreshClicked()">Refresh</button>
结果
点击Refresh会更新refreshToken
实际运用中,需要改成系统自动管理生成RefreshToken。
Gitee获取源码: