feat: NavMenu 로그아웃 버튼 + 토큰 갱신 로직

1. NavMenu에 사용자명 표시 및 로그아웃 버튼 추가
2. CustomAuthenticationStateProvider에 토큰 만료 검증 추가
3. Routes.razor 간소화 (AuthorizeRouteView 사용)
4. 미인증 사용자는 _Imports.razor의 [Authorize]로 보호됨

테스트 계정: admin / admin123

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-06-26 22:12:04 +09:00
parent 6423713305
commit 164d121992
3 changed files with 56 additions and 9 deletions
@@ -1,3 +1,4 @@
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Microsoft.AspNetCore.Components.Authorization;
@@ -27,6 +28,13 @@ public class CustomAuthenticationStateProvider : AuthenticationStateProvider
return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
}
if (IsTokenExpired(token))
{
_logger.LogWarning("토큰 만료됨");
await _localStorage.RemoveItemAsync("auth_token");
return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
}
var principal = _authService.ValidateToken(token);
if (principal == null)
{
@@ -46,8 +54,6 @@ public class CustomAuthenticationStateProvider : AuthenticationStateProvider
public async Task LoginAsync(string token)
{
await _localStorage.SetItemAsStringAsync("auth_token", token);
var principal = _authService.ValidateToken(token);
NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
}
@@ -56,4 +62,18 @@ public class CustomAuthenticationStateProvider : AuthenticationStateProvider
await _localStorage.RemoveItemAsync("auth_token");
NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
}
private bool IsTokenExpired(string token)
{
try
{
var handler = new JwtSecurityTokenHandler();
var jwtToken = handler.ReadJwtToken(token);
return jwtToken.ValidTo < DateTime.UtcNow;
}
catch
{
return true;
}
}
}