fix: DelegatingHandler와 TokenStore의 생명주기 불일치(Scope Capture) 문제 해결을 위한 IServiceProvider 동적 해석(Resolve) 적용
TaxBaik CI/CD / build-and-deploy (push) Successful in 54s
TaxBaik CI/CD / build-and-deploy (push) Successful in 54s
This commit is contained in:
@@ -10,12 +10,12 @@ using System.Text.Json;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class TokenRefreshHandler : DelegatingHandler
|
public class TokenRefreshHandler : DelegatingHandler
|
||||||
{
|
{
|
||||||
private readonly ITokenStore _tokenStore;
|
private readonly IServiceProvider _serviceProvider;
|
||||||
private readonly ILogger<TokenRefreshHandler> _logger;
|
private readonly ILogger<TokenRefreshHandler> _logger;
|
||||||
|
|
||||||
public TokenRefreshHandler(ITokenStore tokenStore, ILogger<TokenRefreshHandler> logger)
|
public TokenRefreshHandler(IServiceProvider serviceProvider, ILogger<TokenRefreshHandler> logger)
|
||||||
{
|
{
|
||||||
_tokenStore = tokenStore;
|
_serviceProvider = serviceProvider;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,10 +23,13 @@ public class TokenRefreshHandler : DelegatingHandler
|
|||||||
HttpRequestMessage request,
|
HttpRequestMessage request,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
// 최신 Scoped ITokenStore 실시간 해석 (Scope Capture 차단 및 기존 Blazor 회로 수명 공유)
|
||||||
|
var tokenStore = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService<ITokenStore>(_serviceProvider);
|
||||||
|
|
||||||
// 요청에 access token 추가
|
// 요청에 access token 추가
|
||||||
if (!string.IsNullOrEmpty(_tokenStore.AccessToken))
|
if (!string.IsNullOrEmpty(tokenStore.AccessToken))
|
||||||
{
|
{
|
||||||
request.Headers.Authorization = new("Bearer", _tokenStore.AccessToken);
|
request.Headers.Authorization = new("Bearer", tokenStore.AccessToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
var response = await base.SendAsync(request, cancellationToken);
|
var response = await base.SendAsync(request, cancellationToken);
|
||||||
@@ -34,15 +37,15 @@ public class TokenRefreshHandler : DelegatingHandler
|
|||||||
// 401 응답이면 토큰 갱신 시도
|
// 401 응답이면 토큰 갱신 시도
|
||||||
if (response.StatusCode == HttpStatusCode.Unauthorized)
|
if (response.StatusCode == HttpStatusCode.Unauthorized)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(_tokenStore.RefreshToken))
|
if (!string.IsNullOrEmpty(tokenStore.RefreshToken))
|
||||||
{
|
{
|
||||||
var newTokenPair = await RefreshTokenAsync(_tokenStore.RefreshToken, request, cancellationToken);
|
var newTokenPair = await RefreshTokenAsync(tokenStore.RefreshToken, request, cancellationToken);
|
||||||
if (newTokenPair != null)
|
if (newTokenPair != null)
|
||||||
{
|
{
|
||||||
// TokenStore에 토큰 저장
|
// TokenStore에 토큰 저장
|
||||||
_tokenStore.AccessToken = newTokenPair.AccessToken;
|
tokenStore.AccessToken = newTokenPair.AccessToken;
|
||||||
_tokenStore.RefreshToken = newTokenPair.RefreshToken;
|
tokenStore.RefreshToken = newTokenPair.RefreshToken;
|
||||||
_tokenStore.TokenExpiryTicks = DateTime.UtcNow.AddSeconds(newTokenPair.ExpiresIn).Ticks;
|
tokenStore.TokenExpiryTicks = DateTime.UtcNow.AddSeconds(newTokenPair.ExpiresIn).Ticks;
|
||||||
|
|
||||||
// 새 토큰으로 재요청
|
// 새 토큰으로 재요청
|
||||||
request.Headers.Authorization = new("Bearer", newTokenPair.AccessToken);
|
request.Headers.Authorization = new("Bearer", newTokenPair.AccessToken);
|
||||||
@@ -51,7 +54,7 @@ public class TokenRefreshHandler : DelegatingHandler
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.LogWarning("토큰 갱신 실패 - 로그아웃");
|
_logger.LogWarning("토큰 갱신 실패 - 로그아웃");
|
||||||
_tokenStore.Clear();
|
tokenStore.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user