【发布时间】:2021-10-31 04:14:03
【问题描述】:
我正在使用 angular 和 asp.net 核心我已经在
this artical 的帮助下实现了 JWT 令牌和刷新令牌我已经编写了代码来检查 Jwt 在 Authguard 中是否有效,如果 jwt 无效,那么使用刷新令牌将调用 api 并获取新的 Jwt 和刷新令牌。仅当我执行刷新页面和导航到另一个页面之类的任何事件时,才会发生这种情况。 我想知道如果我们的 jwt 令牌过期而没有执行任何事件角度检测它并使用referh 令牌自动调用 api 并获取新的 jwt 令牌
这里是代码
authguard
在 authguard 中 isUserAuthenticated() 将检查 jwt 是否已过期,如果已过期,它将使用刷新令牌进行 api 调用并获取新的 jwt 和刷新令牌
async canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Promise<boolean> {
if((await this._authService.isUserAuthenticated()) === true){
return true;
}
else{
this._router.navigate([RouteConstant.SIGN_IN]);
return false;
}
}
public async isUserAuthenticated(){
if(this._storageService.getToken() !== null){
if(!this._jwtHelperService.isTokenExpired(this._storageService.getToken()?.toString())){
return true;
}
else{
if(!this._storageService.refreshTokenExists()){
return false;
}
else{
let authTokenClient: AuthTokenClient = {
token: this._storageService.getToken() as string,
refreshToken: this._storageService.getRefreshToken() as string
};
let response: AuthToken = await this._serverService.refreshAuthToken(authTokenClient).toPromise<AuthToken>();
console.log(response);
this.setAuth(response);
return !this._jwtHelperService.isTokenExpired(this._storageService.getToken()?.toString());
}
}
}
else{
return false;
}
}
}
public setAuth(authToken: AuthToken){
this._storageService.saveToken(authToken.token?.toString());
this._storageService.saveRefreshToken(authToken.refreshToken);
}
public async refreshAuthToken(authTokenClient: AuthTokenClient) {
const response = await this._http.post<AuthToken>(environment.apiHost + UrlConstant.ACCOUNT_REFRESH, authTokenClient,{observe: 'response'}).toPromise();
console.log(response);
const newToken = (<any>response).body.token;
console.log(newToken);
const newRefreshToken = (<any>response).body.refreshToken;
console.log(newRefreshToken);
localStorage.setItem("token", newToken);
localStorage.setItem("refreshToken",newRefreshToken);
if (newToken && newRefreshToken == null){
return false
}
else {
return true;
}
}
Startup.cs
services.AddAuthentication(opt =>
{
opt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
opt.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = jwtSettings.ValidIssuer,
ValidAudience = jwtSettings.ValidAudience,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration[ConfigurationKeyConstant.JWT_SECRET_KEY])),
ClockSkew = TimeSpan.Zero
};
});
Controller.cs
[Route("refresh")]
public IActionResult Refresh(AuthTokenBase authTokenBase)
{
if (authTokenBase is null)
{
return BadRequest("Invalid client request");
}
string accessToken = authTokenBase.Token;
string refreshToken = authTokenBase.RefreshToken;
var principal = this._jwtHandler.GetPrincipalFromExpiredToken(accessToken);
var username = principal.Identity.Name;
string newAccessToken = this._jwtHandler.GenerateToken();
string newRefreshToken = this._jwtHandler.GenerateRefreshToken();
return Ok(new AuthToken()
{
Token = newAccessToken,
RefreshToken = newRefreshToken,
IsAuthSuccessful = true
});
}
【问题讨论】:
-
我们使用一个可观察的计时器在令牌过期之前进行刷新,但是在刷新期间有调用出去时会变得复杂。你为什么要这样做?为什么默认实现不好?
-
@MotKohn 正如你在网上提到的可观察计时器并发现有时间间隔,所以我在我的代码中使用它
import { interval, Observable, Subscription } from "rxjs"; timer: any; constructor(private _authservice: AuthService, private _storageService: StorageService) { } ngOnInit() { this.timer = interval(60000).subscribe(x => { this._authservice.isUserAuthenticated(); });这是正确的方式吗?? -
这就是我的意思,但再说一遍:当您使旧令牌无效且尚未取回新令牌时发生的调用,您将如何处理?这就是 authguard 以这种方式实现的原因。
-
@MotKohn 因为我没有在 Startup.cs 中设置
ClockSkew=TimeSpan.Zero=> 在 asp.net-core 中配置,所以即使在我的令牌过期后,服务器也会允许直到 5 分钟,这是默认的 @987654327 @。因为我将 JWT 令牌的到期时间保持为 5 分钟,并保持检查有效性的时间间隔为 4 分钟。所以我认为这样我的通话将永远成功
标签: c# angular jwt refresh-token