Files
caliverse_server/BrokerApiServer/Common/RequireAdminAuthAttribute.cs
2025-11-28 16:54:56 +09:00

94 lines
3.7 KiB
C#

using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.IdentityModel.Tokens;
using ServerCore;
namespace BrokerApiServer;
using BrokerApiCore;
/// <summary>
/// 엑세스 토큰 인증이 필요한 컨트롤러를 지정하는 애노테이션(Attribute) 정의
/// 밴 상태 체크 이슈
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class RequireAdminAuthAttribute : System.Attribute, IAsyncActionFilter
{
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
// require 서비스 가져오기
// var planet_service = context.HttpContext.RequestServices.GetRequiredService<PlanetService>();
// Guard.Against.isNull(planet_service, ServerErrorCode.InternalServerError, "PlanetService가 di에 등록돼 있지 않음");
var auth_header = context.HttpContext.Request.Headers.Authorization.FirstOrDefault() ?? string.Empty;
Guard.Against.isNullOrEmptyOrWhiteSpace(auth_header, ServerErrorCode.InvalidPlanetJwt, ()=>"empty jwt");
Guard.Against.isFalse(auth_header.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase),
ServerErrorCode.InvalidUserJwt, ()=>"인증 토큰 오류");
// "Bearer " 이후의 토큰 부분을 추출합니다.
var token = auth_header["Bearer ".Length..].Trim();
context.HttpContext.Items["admin_id"] = validate(token);
await next();
}
//==========================================
// secret_key: '81b659967735aea6e4cb0467d04ea12c4a6432b415254f59825055680f59a9823fec5a15e9adbd246b1365ef1522580477691bc5cb56a9364143e7d9385d9912'
// jdbc-url: jdbc:mysql://10.20.20.8:3306/caliverse?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
// username: external_ro
// password: bQNEXbRWQTtV6bwlqktGyBiuf2KqYF
// token
// eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJiZW9tY2h1bC5qYW5nQGxvdHRlLm5ldCIsImlhdCI6MTcyOTc1MzkzNiwiZXhwIjoxNzI5ODQwMzM2fQ.TzLFPigDZIYkxZa3JNdE2kHPxTBkCevwqtcWgz8tMnA
//==========================================
// todo: admin 관련 시크릿을 config에서 정의하여 사용할 것
private string validate(string jwt)
{
const string admin_pass_token = "p8qcZBraFCGfm2QeIGkJBynb6ULKhi6wGlnCDXvKTnM";
if (jwt == admin_pass_token)
{
return "park.chanheon@lotte.net";
}
var principal = parseToken(jwt);
Guard.Against.isNull(principal, ServerErrorCode.InvalidUserJwt, ()=>"jwt parsing error");
// var exp_time = DateTimeOffset.FromUnixTimeSeconds(long.Parse(exp_claim ?? string.Empty));
// Guard.Against.isFalse(exp_time > DateTimeOffset.UtcNow, ServerErrorCode.ExpiredPlanetJwt, "Jwt has expired");
return principal.FindFirstValue(JwtRegisteredClaimNames.Sub) ?? string.Empty;
}
public ClaimsPrincipal? parseToken(string token)
{
const string admin_secret_key = "81b659967735aea6e4cb0467d04ea12c4a6432b415254f59825055680f59a9823fec5a15e9adbd246b1365ef1522580477691bc5cb56a9364143e7d9385d9912";
var token_handler = new JwtSecurityTokenHandler();
// 시크릿 키를 바이트 배열로 변환
var key = Encoding.UTF8.GetBytes(admin_secret_key);
// 토큰 검증 매개변수 설정
var validation_parameters = new TokenValidationParameters
{
ValidateIssuer = false,
ValidateAudience = false,
ValidIssuer = "",
ValidAudience = "",
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key)
};
try
{
// 토큰 검증 및 클레임 추출
var principal = token_handler.ValidateToken(token, validation_parameters, out var validated_token);
return principal;
}
catch (SecurityTokenException ex)
{
Log.getLogger().error($"admin JWT 파싱 에러 => {ex.Message}");
}
return null;
}
}