보안: 기본 인증
- 본 번역문서의 원문은 Security: Basic Authentication www.asp.net 입니다.
기본 인증은 RFC 2617, HTTP Authentication: Basic and Digest Access Authentication 문서에 정의되어 있습니다.
장점 | 단점 |
---|---|
|
|
기본 인증은 다음과 같이 동작합니다:
- 인증이 필요한 요청인 경우, 서버가 상태 코드 401(인증되지 않음)을 반환합니다. 이 응답에는 서버가 기본 인증을 지원함을 의미하는 WWW-Authenticate 헤더가 포함됩니다.
- 클라이언트가 Authorization 헤더에 클라이언트의 자격 증명을 설정한 새로운 요청을 전송합니다. 이 자격 증명은 Base64로 인코딩 된, "이름:비밀번호" 포멧의 문자열입니다. 즉, 자격 증명은 암호화되지 않습니다.
기본 인증은 "영역(Realm)"의 문맥에서 수행됩니다. 이 영역의 이름은 서버가 WWW-Authenticate 헤더를 통해서 지정합니다. 그리고, 사용자의 자격 증명은 바로 이 영역 안에서만 유효합니다. 이 영역의 정확한 범위는 서버에 의해서 정의됩니다. 가령, 자원들을 분할하기 위한 목적으로 여러 영역을 정의할 수도 있습니다.
그리고, 기본 인증에서는 자격 증명이 암호화되지 않은 상태로 전송되기 때문에 HTTPS를 사용하는 경우에만 안전합니다. 이에 관한 보다 자세한 정보는 보안: Web API에서 SSL 사용하기 문서를 참고하시기 바랍니다.
또한, 기본 인증은 CSRF(크로스 사이트 요청 위조) 공격에도 매우 취약합니다. 일단 사용자가 자격 증명을 입력하고 나면, 세션이 유지되는 동안, 같은 도메인에 대한 요청들을 전송할 때, 브라우저가 자동으로 자격 증명을 함께 전송합니다. 이 점은 AJAX 요청의 경우도 마찬가지 입니다. 이 문제에 관해서는 보안: 크로스 사이트 요청 위조(Cross-Site Request Forgery) 공격 방지하기 문서를 참고하시기 바랍니다.
IIS와 기본 인증
IIS도 기본 인증을 지원하기는 하지만, 한 가지 주의해야 할 점이 있습니다. 바로, 사용자가 자신의 Windows 자격 증명을 통해서 인증된다는 점입니다. 결국, 이 얘기는 사용자가 반드시 서버의 도메인에 속한 계정을 갖고 있어야만 한다는 뜻입니다. 그러나, 공개된 웹 사이트인 경우, 대부분 ASP.NET 멤버십 공급자를 통해서 인증 받는 것이 일반적일 것입니다.
IIS를 이용한 기본 인증을 활성화시키려면, 먼저 ASP.NET 프로젝트의 Web.config에서 인증 모드를 "Windows"로 설정합니다:
<system.web> <authentication mode="Windows" /> </system.web>
이 모드에서 IIS는 인증을 위해서 Windows 자격 증명을 사용합니다. 그리고, IIS에서 기본 인증도 활성화시켜야 합니다. IIS 관리자에서 기능 보기(Features View)로 이동한 다음, 인증(Authentication)을 선택하고 기본 인증(Basic authentication)을 활성화시킵니다.
마지막으로, Web API 프로젝트에서는 인증이 필요한 모든 컨트롤러 액션에 [Authorize]
어트리뷰트를 추가합니다.
클라이언트는 요청에 Authorization 헤더를 설정해서 직접 인증을 수행하게 됩니다. 클라이언트가 브라우저인 경우에는 자동으로 이 과정이 수행됩니다. 반면, 클라이언트가 브라우저가 아니라면, 직접 이 헤더를 설정해줘야 합니다. 다음 C# 예제에서는 사용자의 기본 자격 증명을 전송하기 위해서 HttpClient를 사용하고 있습니다:
HttpClientHandler handler = new HttpClientHandler() { UseDefaultCredentials = true }; HttpClient client = new HttpClient(handler); client.BaseAddress = new Uri("https://localhost"); var response = client.GetAsync("api/values").Result;
또는, HttpClientHandler의 Credentials 속성을 이용해서 자격 증명을 설정할 수도 있습니다:
HttpClientHandler handler = new HttpClientHandler(); handler.Credentials = new NetworkCredential("username", "password"); HttpClient client = new HttpClient(handler);
사용자 지정 멤버십을 이용한 기본 인증
이미 살펴본 것처럼 IIS 내장 기본 인증은 Windows 자격 증명을 사용합니다. 결국 이 말은, 호스팅 서버에 사용자의 계정을 생성해야 한다는 뜻입니다. 그러나, 인터넷 응용 프로그램에서는 대부분 사용자 계정을 외부 데이터베이스에 저장합니다.
다음 코드는 기본 인증을 수행하는 HTTP 모듈을 보여주고 있습니다.
이 예제 코드에 임시로 구현되어 있는 CheckPassword
더미 메서드만 수정하면 ASP.NET 멤버십 공급자를 이용하도록 간단하게 변경할 수 있습니다
namespace WebHostBasicAuth.Modules { public class BasicAuthHttpModule : IHttpModule { private const string Realm = "My Realm"; 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; } } // TODO: Here is where you would validate the username and password. private static bool CheckPassword(string username, string password) { return username == "user" && password == "password"; } private static bool AuthenticateUser(string credentials) { bool validated = false; try { var encoding = Encoding.GetEncoding("iso-8859-1"); credentials = encoding.GetString(Convert.FromBase64String(credentials)); int separator = credentials.IndexOf(':'); string name = credentials.Substring(0, separator); string password = credentials.Substring(separator + 1); validated = CheckPassword(name, password); if (validated) { var identity = new GenericIdentity(name); SetPrincipal(new GenericPrincipal(identity, null)); } } catch (FormatException) { // Credentials were not formatted correctly. validated = false; } return validated; } 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 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() { } } }
이 HTTP 모듈을 활성화시키려면 web.config 파일의 system.webServer 섹션에 다음 구성을 추가하면 됩니다:
<system.webServer> <modules> <add name="BasicAuthHttpModule" type="WebHostBasicAuth.Modules.BasicAuthHttpModule, BasicAuth"/> </modules>
- 여러분의 첫 번째 ASP.NET Web API (C#) 2013-05-27 20:30
- CRUD 작업을 지원하는 Web API 작성하기 2013-06-14 20:30
- ASP.NET 웹폼에서 Web API 사용하기 2013-06-25 20:30
- ASP.NET Web API와 라우팅 2013-07-10 20:30
- ASP.NET Web API 도움말 페이지 작성하기 2013-08-14 15:43
- .NET 클라이언트에서 Web API 호출하기 (C#) 2013-08-21 16:26
- WPF 응용 프로그램에서 Web API 호출하기 (C#) 2013-08-28 22:41
- HttpClient 메시지 처리기 2013-09-04 17:16
- ASP.NET Web API 예외 처리 2013-09-11 21:23
- HTML 폼 데이터 전송하기 - 파트 1 2013-09-18 21:23
- HTML 폼 데이터 전송하기 - 파트 2 2013-09-25 01:11
- ASP.NET Web API와 HTTP 쿠키 2013-10-02 09:00
- 자체-호스트(Self-Host) Web API (C#) 2013-10-09 15:59
- OWIN을 이용한 ASP.NET Web API 자체 호스트(Self-Host) 2014-01-17 08:00
- 보안: ASP.NET Web API의 인증(Authentication)과 권한(Authorization) 2014-01-20 08:00
- 보안: 기본 인증 2014-01-22 08:00
- 보안: ASP.NET Web API와 개별 사용자 계정 2014-01-24 08:00
- 보안: 폼 인증 2014-01-27 08:00
- 보안: 통합 Windows 인증 2014-01-29 08:00
- 보안: 크로스 사이트 요청 위조(Cross-Site Request Forgery) 공격 방지하기 2014-02-03 08:00
- 보안: Web API에서 SSL 사용하기 2014-02-05 08:00
- 보안: 외부 인증 서비스 (C#) 2014-02-07 08:00
- 보안: ASP.NET Web API 교차-원본 요청(Cross-Origin Request) 활성화하기 2014-02-10 08:00