55 lines
2.0 KiB
C#
55 lines
2.0 KiB
C#
using System.Security.Cryptography;
|
|
using System.Text;
|
|
|
|
namespace GameServer.Services
|
|
{
|
|
/// <summary>
|
|
/// 포트폴리오 관리자 인증 도우미.
|
|
/// appsettings.json 의 Portfolio:AdminPassword 값을 읽어 비밀번호를 검증한다.
|
|
/// Program.cs 에서 싱글턴으로 등록된다.
|
|
/// </summary>
|
|
public class PortfolioAdminAuth
|
|
{
|
|
// 게임 API 와 섞이지 않도록 포트폴리오 전용 쿠키 인증 스킴을 사용한다.
|
|
public const string CookieScheme = "PortfolioAdminCookie";
|
|
|
|
// 관리자 전용 인가 정책 이름.
|
|
public const string PolicyName = "PortfolioAdmin";
|
|
|
|
// 비밀번호가 아직 설정되지 않았음을 뜻하는 기본 자리표시자 값.
|
|
private const string PlaceholderPassword = "CHANGE_ME";
|
|
|
|
private readonly string? _password;
|
|
|
|
public PortfolioAdminAuth(IConfiguration config)
|
|
{
|
|
_password = config["Portfolio:AdminPassword"];
|
|
}
|
|
|
|
/// <summary>
|
|
/// 실제 비밀번호가 설정되어 있는지 여부.
|
|
/// 값이 비어 있거나 자리표시자(CHANGE_ME) 그대로면 false.
|
|
/// </summary>
|
|
public bool IsConfigured =>
|
|
!string.IsNullOrWhiteSpace(_password) &&
|
|
!string.Equals(_password, PlaceholderPassword, StringComparison.Ordinal);
|
|
|
|
/// <summary>
|
|
/// 비밀번호를 상수 시간으로 비교한다. 미설정 상태면 언제나 false.
|
|
/// 길이 차이로 조기 종료되지 않도록 양쪽 모두 SHA-256 해시로 만든 뒤 비교한다.
|
|
/// </summary>
|
|
public bool Verify(string? password)
|
|
{
|
|
if (!IsConfigured)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
byte[] expected = SHA256.HashData(Encoding.UTF8.GetBytes(_password!));
|
|
byte[] actual = SHA256.HashData(Encoding.UTF8.GetBytes(password ?? string.Empty));
|
|
|
|
return CryptographicOperations.FixedTimeEquals(expected, actual);
|
|
}
|
|
}
|
|
}
|