[英]Issue with JWT token multiple simultaneously refresh with Refresh token
工具:.NET 6 和 EF Core,Vue 3 和 Axios。
R-Token 是刷新令牌。 DB是數據庫。
我有 JWT + Refresh Token auth 的簡單實現。
所以,在客戶端,我有一些調用服務器的間隔操作。 有時,它們會同時執行,如果 JWT 令牌過期,我很少收到使用相同 R 令牌同時刷新令牌的請求。
問題是:在這種情況下,第一個請求會刪除 R-token 並生成新的,然后下一個請求將失敗。
這個問題我該怎么辦?
我對此的看法:
請幫忙。
Axios 攔截器:
instance.interceptors.response.use(response => response,
async (error) => {
const status = error.response ? error.response.status : undefined
const originalRequest = error.config
if(status === 401) {
originalRequest._retry = true
let tryRefresh = await store.dispatch('auth/TryRefreshToken')
if(tryRefresh === false) {
store.dispatch('auth/Logout')
return Promise.reject(error)
}
originalRequest.headers['Authorization'] = 'Bearer ' + store.getters['auth/auth'].accessToken
return instance(originalRequest)
}
if (status === undefined)
{
return Promise.reject(error)
}
return Promise.reject(error)
}
)
控制器中的 .NET 刷新令牌操作:
[HttpPost, Route("Refresh/{refreshToken}")]
[ProducesResponseType(typeof(AuthenticationResponse), 200)]
public IActionResult RefreshTokens(string refreshToken)
{
Request.Headers.TryGetValue("Authorization", out var accessTokenHeader);
string? accessToken = accessTokenHeader.FirstOrDefault()?.Replace("Bearer", string.Empty).Trim();
if (string.IsNullOrEmpty(accessToken)) return BadRequest("No access token presented.");
JwtSecurityToken? expiredToken = new JwtSecurityTokenHandler().ReadToken(accessToken) as JwtSecurityToken;
if (expiredToken is null) return BadRequest("Bad access token format");
IEnumerable<Claim> claims = expiredToken.Claims;
if (int.TryParse(claims.FirstOrDefault(x => x.Type == "User:Id")?.Value, out int userId) is false)
return BadRequest("No user id in token presented");
User? user = _mainContext.Users.AsNoTrackingWithIdentityResolution()
.Include(x => x.Roles)
.FirstOrDefault(x => x.Id == userId);
if (user is null) return NotFound("No user found");
var userDto = user.ToUserDto();
if (_refreshTokenManager.IsTokenValid(refreshToken, user.Id) is false)
return StatusCode(403);
try {
_refreshTokenManager.RemoveToken(refreshToken);
}
catch (Exception ex) {
Log.Error(ex, "Error in used refresh token deletion.");
}
JwtSettingsDto jwtSettings = _configuration.GetSection("Authorization:Jwt").Get<JwtSettingsDto>();
string newAccessToken = _tokenGeneratorService.GenerateAccessJwtToken(userDto, jwtSettings);
string newRefreshToken = _refreshTokenManager.CreateToken(userDto, Request);
return Ok(new AuthenticationResponse(newAccessToken, newRefreshToken, user.Login, user.DisplayName));
}
當刷新令牌有一次性使用時,這幾天推薦使用,同步令牌刷新是客戶端的責任。 如果多個視圖同時調用 API,則 UI 需要這樣做。
在一個實用程序類中執行此操作相當容易,該類對令牌刷新的承諾進行排隊,然后只對其中的第一個進行實際的 HTTP 調用,然后為所有請求返回相同的結果。
例如,請參閱我的這個 ConcurrentActionHandler 類,在 React SPA 中使用,它是從此 API 客戶端代碼調用的。
在您的情況下,Michael Levy 發布的攔截器類似乎做了同樣的工作。 所以這可能是最好的選擇。 但是,相同的設計模式可以應用於其他類型的客戶端,例如用 Swift 或 Kotlin 編碼的移動應用程序。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.