.NET MVC의 Web API에 Basic인증을 적용하는 방법
.NET MVC의 Web API에 Basic인증을 적용하는 방법
↑의 「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