Asp.Net Core 요청 헤더 사용자 정의 인증 추가 예

앞말


작은 프로젝트에 Api 요청 권한 인증을 추가하고 전용 네트워크에서만 사용해야 하기 때문에 간단하게 인증 아래 접근할 수 있는지 확인하는 동시에 학습하는 과정이기도 합니다. 간단하게 기록하기

요점


IAuthenticationHandler 인터페이스 구현: 4가지 방법
  • 우선 InitializeAsync를 호출하여 scheme와 context를 얻습니다
  • 그리고 Authenticate Async를 호출합니다. 여기서 context의 Header에서 전달해야 할 검증 정보를 얻고 관련 검증을 합니다. 결과에 따라 각각 Challenge Async나 Forbid Async를 호출합니다
  • 
    public class HeaderAuth : IAuthenticationHandler {
    
           public AuthenticationScheme Scheme { get; private set; }
    
           public HttpContext CurrentContext { get; private set; }
           public Task<AuthenticateResult> AuthenticateAsync() {
               var token = CurrentContext.Request.Headers[GuidToken.GUID_TOKEN_KEY].ToString();
    
               var (isValid, tokenEntity) = GuidToken.Valid(token);
    
               if (!isValid || tokenEntity == null) {
                   return Task.FromResult(AuthenticateResult.Fail(" 。"));
               }
               //   AuthenticationTicket
               AuthenticationTicket ticket = new AuthenticationTicket(tokenEntity.ToClaimsPrincipal(), Scheme.Name);
               return Task.FromResult(AuthenticateResult.Success(ticket));
           }
    
           public Task ChallengeAsync(AuthenticationProperties properties) {
               CurrentContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
               return Task.CompletedTask;
           }
    
           public Task ForbidAsync(AuthenticationProperties properties) {
               CurrentContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
               return Task.CompletedTask;
           }
    
           public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context) {
               Scheme = scheme;
               CurrentContext = context;
               return Task.CompletedTask;
           }
       }

    Guid Token 클래스는 저희가 사용자 정의한 token 관리자입니다.

    
    public class GuidToken {
            public const string GUID_TOKEN_NAME = "MtGuidTokenAuthentication";
            public const string DEFAULT_AUTHENTICATION_TYPE = "local";
            public const int TOKEN_LENGTH = 32;
            public const string GUEST = "GUEST";
            public const string DEFAULT_ROLE = "USER";
            public const string DEFAULT_OPENID = "DEFAULT_OPENID";
            public const string GUID_TOKEN_KEY = "Token";
            private static int expireDuration = 0;
            public string OpenId { get; set; }
            public string Role { get; set; }
            public DateTime Expire { get; set; }
    
            private static readonly Dictionary<string, GuidToken> tokenCache = new Dictionary<string, GuidToken>();
    
            public static (bool, GuidToken) Valid(string token) {
                if (string.IsNullOrEmpty(token) || token.Length != TOKEN_LENGTH) {
                    return (false, null);
                }
    
                //   Session  
                GuidToken tokenEntity = GetTokenCache();
    
                if (tokenEntity == null) {
                    return (false, null);
                } else {
                    tokenEntity.Expire = DateTime.Now.AddMinutes(expireDuration);
                }
    
                return (true, tokenEntity);
    
                GuidToken GetTokenCache() {
                    if (tokenCache.TryGetValue(token, out var val)) {
                        if (val.Expire > DateTime.Now) return val;
                        else tokenCache.Remove(token);
                    }
                    return null;
                }
    
            }
    
            public static string Create(string openId = DEFAULT_OPENID, string role = DEFAULT_ROLE, int minutes = 30) {
                var token = Guid.NewGuid().ToString("N");
                expireDuration = minutes;
                var entity = new GuidToken {
                    OpenId = openId,
                    Role = role,
                    Expire = DateTime.Now.AddMinutes(expireDuration)
                };
                tokenCache.Add(token, entity);
                return token;
            }
    
            /// <summary>
            ///     ClaimsPrincipal
            /// </summary>
            /// <param name="token"></param>
            /// <returns></returns>
            public ClaimsPrincipal ToClaimsPrincipal() {
                var claimsIdentity = new ClaimsIdentity(new Claim[] {
                    new Claim(ClaimTypes.Name, OpenId),
                    new Claim(ClaimTypes.Role, Role),
                }, GuidToken.DEFAULT_AUTHENTICATION_TYPE);
    
                var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
    
                return claimsPrincipal;
            }
        }

    마지막은 사용법이에요.


    Startup에서 구성
    
    public void ConfigureServices(IServiceCollection services) {
        //  
        services.AddAuthentication(options => {
            options.AddScheme<HeaderAuth>(GuidToken.GUID_TOKEN_NAME, "Default Guid Token");
            options.DefaultAuthenticateScheme = GuidToken.GUID_TOKEN_NAME;
            options.DefaultChallengeScheme = GuidToken.GUID_TOKEN_NAME;
        });
    }
    
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
        if (env.IsDevelopment()) {
            app.UseDeveloperExceptionPage();
        }
        app.UseCors("any");
        app.UseStaticFiles();
        //  
        app.UseAuthentication();
        app.UseRouting();
        //  
        app.UseAuthorization();
        app.UseEndpoints(endpoints => {
            endpoints.MapControllers();
        });
    }
    컨트롤러에서 태그 사용하기
    
    [Authorize]
    public class JobController : ControllerBase {}
    지금까지 Asp였습니다.Net Core 요청 헤더 사용자 정의 인증의 예에 대한 자세한 내용을 추가합니다.Net Core 헤더 인증 요청 자료 추가

    좋은 웹페이지 즐겨찾기