57269e281d
TaxBaik CI/CD / build-and-deploy (push) Failing after 36s
분리의 단점을 제거하고 단일 앱으로 통합: 구조 변경: - TaxBaik.Admin → TaxBaik.Web/Components/Admin/ - Admin Services → TaxBaik.Web/Services/ - 포트: 5001 (기존 5002 제거) 경로: - 홈페이지: http://localhost:5001/taxbaik - 관리자: http://localhost:5001/taxbaik/admin 기술: - Razor Pages (Web) + Blazor Server (Admin) 통합 - 단일 Program.cs로 양쪽 모두 지원 - JWT 인증 유지 - MudBlazor UI 유지 장점: - 개발 복잡도 감소 (터미널 1개) - 배포 단순화 (앱 1개) - DB 마이그레이션 1회 실행 Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
80 lines
2.5 KiB
C#
80 lines
2.5 KiB
C#
using System.IdentityModel.Tokens.Jwt;
|
|
using System.Security.Claims;
|
|
using Microsoft.AspNetCore.Components.Authorization;
|
|
|
|
namespace TaxBaik.Web.Services;
|
|
|
|
public class CustomAuthenticationStateProvider : AuthenticationStateProvider
|
|
{
|
|
private readonly ILocalStorageService _localStorage;
|
|
private readonly AuthService _authService;
|
|
private readonly ILogger<CustomAuthenticationStateProvider> _logger;
|
|
|
|
public CustomAuthenticationStateProvider(ILocalStorageService localStorage, AuthService authService, ILogger<CustomAuthenticationStateProvider> logger)
|
|
{
|
|
_localStorage = localStorage;
|
|
_authService = authService;
|
|
_logger = logger;
|
|
}
|
|
|
|
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
|
|
{
|
|
try
|
|
{
|
|
var token = await _localStorage.GetItemAsStringAsync("auth_token");
|
|
|
|
if (string.IsNullOrEmpty(token))
|
|
{
|
|
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)
|
|
{
|
|
await _localStorage.RemoveItemAsync("auth_token");
|
|
return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
|
|
}
|
|
|
|
return new AuthenticationState(principal);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "인증 상태 조회 중 오류 발생");
|
|
return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
|
|
}
|
|
}
|
|
|
|
public async Task LoginAsync(string token)
|
|
{
|
|
await _localStorage.SetItemAsStringAsync("auth_token", token);
|
|
NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
|
|
}
|
|
|
|
public async Task LogoutAsync()
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
}
|