.NET MVC의 Web API에 Basic인증을 적용하는 방법

.NET MVC의 Web API에 Basic인증을 적용하는 방법

.NET MVC의 Web API에 Basic인증을 적용하는 방법

0025-01

↑의 「Web API」를 선택해서 작성한 프로젝트를 기준으로 합니다.

Basic Authentication in ASP.NET Web API

위 링크의 MSDN에 매우 자세하게 설명되어 있기에 기본적인것은 그대로 따라하면 됩니다만 개인적으로 코딩했던 부분을 정리해 보았습니다.

BasicAuthHttpModule.cs

IHttpModule를 상속받아서 Basic인증을 처리할 모듈을 만듭니다.

using System;
using System.Linq;
using System.Net.Http.Headers;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Web;
using TestProject.Base;

namespace TestProject.Base
{
    /// <summary>
    /// HTTP Basic 인증
    /// </summary>
    public class BasicAuthHttpModule : IHttpModule
    {
        private const string Realm = "Test APIs";

        public void Init(HttpApplication context)
        {
            // Register event handlers
            context.AuthenticateRequest += OnApplicationAuthenticateRequest;
            context.EndRequest += OnApplicationEndRequest;
        }

        private static void SetPrincipal(IPrincipal principal)
        {
            Thread.CurrentPrincipal = principal;
            if (HttpContext.Current != null)
            {
                HttpContext.Current.User = principal;
            }
        }

        private static void AuthenticateUser(string credentials)
        {
            try
            {
                var encoding = Encoding.GetEncoding("iso-8859-1");
                credentials = encoding.GetString(Convert.FromBase64String(credentials));

                int separator = credentials.IndexOf(':');
                string username = credentials.Substring(0, separator);
                string password = credentials.Substring(separator + 1);

				// CheckPassword안에서 DB값과 비교하거나 인증 판단을 내린다
                if (CheckPassword(name, password))
                {
					// 인증후의 필요처리
                    var identity = new GenericIdentity(name);
                    SetPrincipal(new GenericPrincipal(identity, null));
                }
                else
                {
                    // Invalid username or password.
                    HttpContext.Current.Response.StatusCode = 401;
                }
            }
            catch (FormatException)
            {
                HttpContext.Current.Response.StatusCode = 401;
            }
        }

        private static void OnApplicationAuthenticateRequest(object sender, EventArgs e)
        {
            var request = HttpContext.Current.Request;
            var authHeader = request.Headers["Authorization"];
            if (authHeader != null)
            {
                var authHeaderVal = AuthenticationHeaderValue.Parse(authHeader);

                // RFC 2617 sec 1.2, "scheme" name is case-insensitive
                if (authHeaderVal.Scheme.Equals("basic", StringComparison.OrdinalIgnoreCase) && authHeaderVal.Parameter != null)
                {
                    AuthenticateUser(authHeaderVal.Parameter);
                    //if (!AuthenticateUser(authHeaderVal.Parameter))
                    //{
                    //    HttpContext.Current.Response.StatusCode = 401;
                    //}
                }
            }
        }

        // If the request was unauthorized, add the WWW-Authenticate header 
        // to the response.
        private static void OnApplicationEndRequest(object sender, EventArgs e)
        {
            var response = HttpContext.Current.Response;
            if (response.StatusCode == 401)
            {
                response.Headers.Add("WWW-Authenticate", string.Format("Basic realm=\"{0}\"", Realm));
            }
        }

        public void Dispose()
        {
        }
    }
}

Web.config

위에서 만든 BasicAuthHttpModule를 web.config에 선언해 줍니다.

<system.web>
    ...
    <authentication mode="Windows" />
</system.web>
<system.webServer>
    <modules>
        ...
        <add name="BasicAuthHttpModule" type="TestProject.Base.BasicAuthHttpModule, TestProject" />
    </modules>
</system.webServer>

TestController.cs

마지막으로 인증을 적용할 Controller Class에 [Authorize] 같이 설정하면 해당 Controller를 부를때 반드시 인증을 거치게 됩니다.

[Authorize]
public class TestController : ApiController

Pie's Tech Note

생계형 개발자의 메모장

comments powered by Disqus

    rss facebook twitter github youtube mail spotify instagram linkedin google google-plus pinterest medium vimeo stackoverflow reddit quora