Share via


.NET을 사용하여 모듈 개발

작성자 : Mike Volodarsky

소개

IIS 7.0 이상에서는 다음 두 가지 방법으로 개발된 모듈별로 서버를 확장할 수 있습니다.

  • 관리 코드 및 ASP.NET 서버 확장성 API 사용
  • 네이티브 코드 및 IIS 네이티브 서버 확장성 API 사용

이전에는 ASP.NET 요청 처리 파이프라인이 기본 서버 요청 파이프라인과 분리되었기 때문에 ASP.NET 모듈의 기능이 제한되었습니다.

IIS에서 관리되는 모듈은 통합 파이프라인 아키텍처를 사용하는 네이티브 모듈만큼 강력해집니다. 가장 중요한 것은 관리되는 모듈이 제공하는 서비스는 이제 ASPX 페이지와 같은 콘텐츠를 ASP.NET 요청뿐만 아니라 서버에 대한 모든 요청에 적용할 수 있습니다. 관리되는 모듈은 네이티브 모듈과 일관된 방식으로 구성되고 관리되며 네이티브 모듈과 동일한 처리 단계 및 순서로 실행할 수 있습니다. 마지막으로, 관리되는 모듈은 여러 가지 추가 및 향상된 ASP.NET API를 통해 요청 처리를 조작하는 광범위한 작업 집합을 수행할 수 있습니다.

이 문서에서는 ASP.NET 2.0 멤버 자격 증명 시스템의 공급자 기반 자격 증명 인프라와 같은 임의의 자격 증명 저장소에 대해 기본 인증을 수행하는 기능을 추가하기 위해 관리되는 모듈을 사용하여 서버를 확장하는 방법을 보여 줍니다.

이렇게 하면 Windows 자격 증명 저장소에 연결된 IIS의 기본 제공 인증 지원을 임의의 자격 증명 저장소를 지원하는 인증 또는 SQL Server, SQL Express 또는 Active Directory와 같은 ASP.NET 2.0과 함께 제공되는 기존 멤버 자격 공급자로 바꿀 수 있습니다.

이 문서에서는 다음 작업을 살펴봅니다.

  • ASP.NET API를 사용하여 관리되는 모듈 개발
  • 서버에 관리되는 모듈 배포

IIS 모듈 및 처리기 개발의 기본 사항에 대한 자세한 내용은 .NET Framework를 사용하여 IIS7 모듈 및 처리기 개발을 참조하세요.

블로그 http://www.mvolo.com/에서 IIS 모듈 작성에 대한 많은 리소스와 팁을 찾을 수 있을 뿐만 아니라 애플리케이션에 대한 기존 IIS 모듈을 다운로드할 수도 있습니다. 몇 가지 예제는 HttpRedirection 모듈을 사용하여 애플리케이션으로 요청 리디렉션, DirectoryListingModule을 사용하여 IIS 웹 사이트에 대한 멋진 디렉터리 목록, IconHandler를 사용하여 ASP.NET 애플리케이션에 예쁜 파일 아이콘 표시를 참조하세요.

참고

이 문서에 제공된 코드는 C#으로 작성되었습니다.

사전 요구 사항

이 문서의 단계를 수행하려면 다음 IIS 기능이 설치되어 있어야 합니다.

ASP.NET

Windows Vista 제어판 통해 ASP.NET 설치합니다. "프로그램" - "Windows 기능 켜기 또는 끄기"를 선택합니다. 그런 다음 "인터넷 정보 서비스" - "World Wide Web Services" - "애플리케이션 개발 기능"을 열고 "ASP.NET"을 검사.

Windows Server® 2008 빌드가 있는 경우 "서버 관리자" - "역할"을 열고 "웹 서버(IIS)"를 선택합니다. "역할 서비스 추가"를 클릭합니다. "애플리케이션 개발" 검사 "ASP.NET".

기본 인증에 대한 배경 정보

기본 인증은 HTTP.1 프로토콜(RFC 2617)에 정의된 인증 체계입니다. 높은 수준에서 다음과 같이 작동하는 표준 챌린지 기반 메커니즘을 사용합니다.

  • 브라우저에서 자격 증명 없이 URL을 요청합니다.
  • 서버에서 해당 URL에 대한 인증이 필요한 경우 401 액세스 거부 메시지로 응답하고 기본 인증 체계가 지원됨을 나타내는 헤더를 포함합니다.
  • 브라우저는 응답을 수신하고 구성된 경우 URL에 대한 다음 요청에 대한 요청 헤더 내에 일반 텍스트로 포함할 사용자 이름/암호를 묻는 메시지를 사용자에게 표시합니다.
  • 서버는 헤더 내에서 사용자 이름/암호를 수신하고 인증에 사용합니다.

참고

이 인증 프로토콜에 대한 자세한 설명은 이 문서의 scope 있지만 기본 인증 체계는 사용자 이름/암호를 일반 텍스트로 전송하므로 SSL을 안전하게 보호해야 한다는 점을 언급할 가치가 있습니다.

IIS에는 로컬 계정 저장소에 저장된 Windows 계정 또는 도메인 계정에 대한 Active Directory에 대한 기본 인증 지원이 포함됩니다. 사용자가 기본 인증을 사용하여 인증할 수 있도록 하지만 대신 ASP.NET 2.0 멤버 자격 서비스를 사용하여 자격 증명의 유효성을 검사하려고 합니다. 이렇게 하면 Windows 계정에 연결하지 않고도 SQL Server와 같은 다양한 기존 멤버 자격 공급자에 사용자 정보를 자유롭게 저장할 수 있습니다.

작업 1: .NET을 사용하여 모듈 개발

이 작업에서는 HTTP.1 기본 인증 체계를 지원하는 인증 모듈의 개발을 살펴봅니다. 이 모듈은 ASP.NET v1.0부터 사용할 수 있는 표준 ASP.NET 모듈 패턴을 사용하여 개발되었습니다. 이 패턴은 IIS 서버를 확장하는 ASP.NET 모듈을 빌드하는 데 사용됩니다. 실제로 이전 버전의 IIS용으로 작성된 기존 ASP.NET 모듈은 IIS에서 사용할 수 있으며, 더 나은 ASP.NET 통합을 활용하여 이를 사용하는 웹 애플리케이션에 더 많은 기능을 제공할 수 있습니다.

참고

모듈의 전체 코드는 부록 A에 제공됩니다.

관리되는 모듈은 System.Web.IHttpModule 인터페이스를 구현하는 .NET 클래스입니다. 이 클래스의 기본 함수는 IIS 요청 처리 파이프라인 내에서 발생하는 하나 이상의 이벤트를 등록한 다음 IIS가 해당 이벤트에 대한 모듈의 이벤트 처리기를 호출할 때 유용한 작업을 수행하는 것입니다.

"BasicAuthenticationModule.cs"라는 새 소스 파일을 만들고 모듈 클래스를 만들 수 있습니다(전체 소스 코드는 부록 A에 제공됨).

public class BasicAuthenticationModule : System.Web.IHttpModule
{
    void Init(HttpApplication context)
    {
    }
    void Dispose()
    {
    }
}

Init 메서드의 기본 함수는 모듈의 이벤트 처리기 메서드를 적절한 요청 파이프라인 이벤트에 배선하는 것입니다. 모듈의 클래스는 이벤트 핸들 메서드를 제공하며 모듈에서 제공하는 원하는 기능을 구현합니다. 이 내용은 자세히 설명합니다.

Dispose 메서드는 모듈 instance 삭제될 때 모듈 상태를 클린 데 사용됩니다. 모듈에서 릴리스해야 하는 특정 리소스를 사용하지 않는 한 일반적으로 구현되지 않습니다.

Init()

클래스를 만든 후 다음 단계는 Init 메서드를 구현하는 것입니다. 유일한 요구 사항은 하나 이상의 요청 파이프라인 이벤트에 대한 모듈을 등록하는 것입니다. System.EventHandler 대리자 서명을 따르는 모듈 메서드를 제공된 System.Web.HttpApplication instance 노출되는 원하는 파이프라인 이벤트에 연결합니다.

public void Init(HttpApplication context)            
{
   //          
   // Subscribe to the authenticate event to perform the 
   // authentication. 
   // 
   context.AuthenticateRequest += new        
              EventHandler(this.AuthenticateUser);

   // 
   // Subscribe to the EndRequest event to issue the 
   // challenge if necessary. 
   // 
   context.EndRequest += new 
              EventHandler(this.IssueAuthenticationChallenge);
}

AuthenticateRequest 이벤트 중 모든 요청에 대해 AuthenticateUser 메서드가 호출됩니다. 이를 활용하여 요청에 있는 자격 증명 정보를 기반으로 사용자를 인증합니다.

IssueAuthenticationChallenge 메서드는 EndRequest 이벤트 중 모든 요청에 대해 호출됩니다. 권한 부여 모듈이 요청을 거부하고 인증이 필요할 때마다 기본 인증 챌린지를 클라이언트에 다시 발급해야 합니다.

AuthenticateUser()

AuthenticateUser 메서드를 구현합니다. 이 메서드는 다음을 수행 합니다.

  • 들어오는 요청 헤더에 있는 경우 기본 자격 증명을 추출합니다. 이 단계의 구현을 보려면 ExtractBasicAuthenticationCredentials 유틸리티 메서드를 참조하세요.
  • 멤버 자격을 통해 제공된 자격 증명의 유효성을 검사하려고 시도합니다(구성된 기본 멤버 자격 공급자 사용). 이 단계의 구현을 보려면 ValidateCredentials 유틸리티 메서드를 참조하세요.
  • 인증에 성공하면 사용자를 식별하는 사용자 주체를 만들고 요청과 연결합니다.

이 처리가 끝나면 모듈이 사용자 자격 증명을 성공적으로 획득하고 유효성을 검사할 수 있는 경우 다른 모듈 및 애플리케이션 코드가 나중에 액세스 제어 결정에 사용하는 인증된 사용자 주체를 생성합니다. 예를 들어 URL 권한 부여 모듈은 애플리케이션에서 구성한 권한 부여 규칙을 적용하기 위해 다음 파이프라인 이벤트에서 사용자를 검사합니다.

IssueAuthenticationChallenge()

IssueAuthenticationChallenge 메서드를 구현합니다. 이 메서드는 다음을 수행 합니다.

  • 응답 상태 코드를 확인하여 이 요청이 거부되었는지 확인합니다.
  • 그렇다면 응답에 기본 인증 챌린지 헤더를 실행하여 클라이언트가 인증하도록 트리거합니다.

유틸리티 메서드

다음을 포함하여 모듈에서 사용하는 유틸리티 메서드를 구현합니다.

  • ExtractBasicAuthenticationCredentials. 이 메서드는 기본 인증 체계에 지정된 대로 권한 부여 요청 헤더에서 기본 인증 자격 증명을 추출합니다.
  • ValidateCredentials. 이 메서드는 멤버 자격을 사용하여 사용자 자격 증명의 유효성을 검사하려고 시도합니다. 멤버 자격 API는 기본 자격 증명 저장소를 추상화하고 구성을 통해 멤버 자격 공급자를 추가/제거하여 자격 증명 저장소 구현을 구성할 수 있도록 합니다.

참고

이 샘플에서는 멤버 자격 유효성 검사가 주석 처리되고 대신 모듈은 사용자 이름과 암호가 모두 "test" 문자열과 같은지 확인합니다. 이는 명확성을 위해 수행되며 프로덕션 배포를 위한 것이 아닙니다. ValidateCredentials 내에서 멤버 자격 코드를 주석 처리 해제하고 애플리케이션에 대한 멤버 자격 공급자를 구성하기만 하면 멤버 자격 기반 자격 증명 유효성 검사를 사용하도록 초대됩니다. 자세한 내용은 부록 C를 참조하세요.

작업 2: 애플리케이션에 모듈 배포

첫 번째 작업에서 모듈을 만든 후 애플리케이션에 추가합니다.

애플리케이션에 배포

먼저 애플리케이션에 모듈을 배포합니다. 여기에는 다음과 같은 몇 가지 옵션이 있습니다.

  • 모듈이 포함된 원본 파일을 애플리케이션의 /App_Code 디렉터리에 복사합니다. 이렇게 하면 모듈을 컴파일할 필요가 없습니다. ASP.NET 애플리케이션이 시작될 때 모듈 형식을 자동으로 컴파일하고 로드합니다. 이 소스 코드를 애플리케이션의 /App_Code 디렉터리 내에 BasicAuthenticationModule.cs로 저장하기만 하면 됩니다. 다른 단계에 익숙하지 않은 경우 이 작업을 수행합니다.

  • 모듈을 어셈블리로 컴파일하고 애플리케이션의 /BIN 디렉터리에 이 어셈블리를 삭제합니다. 이 모듈을 이 애플리케이션에서만 사용할 수 있도록 하고 모듈의 원본을 애플리케이션과 함께 제공하지 않으려는 경우 가장 일반적인 옵션입니다. 명령줄 프롬프트에서 다음을 실행하여 모듈 원본 파일을 컴파일합니다.

    <PATH_TO_FX_SDK>csc.exe /out:BasicAuthenticationModule.dll /target:library BasicAuthenticationModule.cs

    여기서 <PATH_TO_FX_SDK> 는 CSC.EXE 컴파일러를 포함하는 .NET Framework SDK의 경로입니다.

  • 모듈을 강력한 이름의 어셈블리로 컴파일하고 이 어셈블리를 GAC에 등록합니다. 컴퓨터의 여러 애플리케이션에서 이 모듈을 사용하려는 경우 이 옵션을 사용하는 것이 좋습니다. 강력한 이름의 어셈블리를 빌드하는 방법에 대한 자세한 내용은 강력한 이름의 어셈블리 만들기 및 사용을 참조하세요.

애플리케이션의 web.config 파일에서 구성을 변경하기 전에 기본적으로 서버 수준에서 잠긴 일부 구성 섹션의 잠금을 해제해야 합니다. 관리자 권한 명령 프롬프트에서 다음을 실행합니다( > 시작 오른쪽 단추로 Cmd.exe 클릭하고 "관리자 권한으로 실행"을 선택합니다.

%windir%\system32\inetsrv\APPCMD.EXE unlock config /section:windowsAuthentication
%windir%\system32\inetsrv\APPCMD.EXE unlock config /section:anonymousAuthentication

이러한 명령을 실행한 후 애플리케이션의 web.config 파일에서 이러한 구성 섹션을 정의할 수 있습니다.

애플리케이션에서 실행되도록 모듈을 구성합니다. 먼저 새 모듈을 사용하도록 설정하고 사용하는 데 필요한 구성을 포함하는 새 web.config 파일을 만듭니다. 먼저 아래 텍스트를 추가하고 애플리케이션의 루트에 저장합니다(%systemdrive%\inetpub\wwwroot\web.config 기본 웹 사이트에서 루트 애플리케이션을 사용하는 경우).

<configuration> 
    <system.webServer> 
        <modules> 
        </modules> 
        <security> 
            <authentication> 
                <windowsAuthentication enabled="false"/> 
                <anonymousAuthentication enabled="false"/> 
            </authentication> 
        </security> 
    </system.webServer> 
</configuration>

새 기본 인증 모듈을 사용하도록 설정하기 전에 다른 모든 IIS 인증 모듈을 사용하지 않도록 설정합니다. 기본적으로 Windows 인증 및 익명 인증만 사용하도록 설정됩니다. 브라우저에서 Windows 자격 증명으로 인증을 시도하거나 익명 사용자를 허용하지 않도록 하려면 Windows 인증 모듈과 익명 인증 모듈을 모두 사용하지 않도록 설정합니다.

이제 애플리케이션에서 로드한 모듈 목록에 모듈을 추가하여 모듈을 사용하도록 설정합니다. web.config 다시 열고 태그 안에 항목을 추가합니다.<modules>

<add name="MyBasicAuthenticationModule" type="IIS7Demos.BasicAuthenticationModule" />

IIS 관리 도구 또는 APPCMD.EXE 명령줄 도구를 사용하여 모듈을 배포할 수도 있습니다.

이러한 변경 내용이 부록 B에 제공된 후 애플리케이션의 web.config 파일의 최종 내용입니다.

축하합니다. 사용자 지정 기본 인증 모듈 구성을 완료했습니다.

직접 경험해 보겠습니다. 인터넷 Explorer 열고 다음 URL에서 애플리케이션을 요청합니다.

http://localhost/

기본 인증 로그인 대화 상자가 표시됩니다. 액세스 권한을 얻으려면 "사용자 이름:" 필드에 "test"를 입력하고 "Password:" 필드에 "test"를 입력합니다. HTML, JPG 또는 기타 콘텐츠를 애플리케이션에 복사하는 경우 새 BasicAuthenticationModule로도 보호됩니다.

요약

이 문서에서는 애플리케이션에 대한 사용자 지정 관리형 모듈을 개발 및 배포하고 해당 모듈이 애플리케이션에 대한 모든 요청에 대한 서비스를 제공하도록 설정하는 방법을 알아보았습니다.

또한 관리 코드에서 서버 구성 요소를 개발하는 기능도 확인했습니다. 이렇게 하면 Windows 자격 증명 스토리지에서 분리된 기본 인증 서비스를 개발할 수 있습니다.

모험을 즐기는 경우 플러그형 자격 증명 저장소를 지원하도록 ASP.NET 2.0 멤버 자격 증명 애플리케이션 서비스의 기능을 활용하도록 이 모듈을 구성합니다. 자세한 내용은 부록 C를 참조하세요.

블로그 http://www.mvolo.com/에서 IIS 모듈 작성에 대한 많은 리소스와 팁을 찾고 애플리케이션에 대한 기존 IIS 모듈을 다운로드합니다. 몇 가지 예제는 HttpRedirection 모듈을 사용하여 애플리케이션으로 요청 리디렉션, DirectoryListingModule을 사용하여 IIS 웹 사이트에 대한 멋진 디렉터리 목록, IconHandler를 사용하여 ASP.NET 애플리케이션에 예쁜 파일 아이콘 표시를 참조하세요.

부록 A: 기본 인증 모듈 소스 코드

이 소스 코드를 /App_Code 디렉터리 내에 BasicAuthenticationModule.cs로 저장하여 애플리케이션에 신속하게 배포합니다.

참고

메모장을 사용하는 경우 파일을 BasicAuthenticationModule.cs.txt 저장하지 않도록 다른 이름으로 저장: 모든 파일을 설정해야 합니다.

#region Using directives
using System;
using System.Collections;
using System.Text;
using System.Web;
using System.Web.Security;
using System.Security.Principal;
using System.IO;
#endregion
 
namespace IIS7Demos
{
    /// 
    /// This module performs basic authentication. 
    /// For details on basic authentication see RFC 2617. 
    /// 
    /// The basic operational flow is: 
    /// 
    ///     On AuthenticateRequest: 
    ///         extract the basic authentication credentials 
    ///         verify the credentials 
    ///         if succesfull, create the user principal with these credentials 
    /// 
    ///     On SendResponseHeaders: 
    ///         if the request is being rejected with an unauthorized status code (401), 
    ///         add the basic authentication challenge to trigger basic authentication. 
    ///       
    /// 

    public class BasicAuthenticationModule : IHttpModule
    {
        #region member declarations
        public const String     HttpAuthorizationHeader = "Authorization";  // HTTP1.1 Authorization header 
        public const String     HttpBasicSchemeName = "Basic"; // HTTP1.1 Basic Challenge Scheme Name 
        public const Char       HttpCredentialSeparator = ':'; // HTTP1.1 Credential username and password separator 
        public const int        HttpNotAuthorizedStatusCode = 401; // HTTP1.1 Not authorized response status code 
        public const String     HttpWWWAuthenticateHeader = "WWW-Authenticate"; // HTTP1.1 Basic Challenge Scheme Name 
        public const String     Realm = "demo"; // HTTP.1.1 Basic Challenge Realm 
        #endregion

        #region Main Event Processing Callbacks
        public void AuthenticateUser(Object source, EventArgs e)
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;
            String userName = null;
            String password = null;
            String realm = null;
            String authorizationHeader = context.Request.Headers[HttpAuthorizationHeader];

            // 
            //  Extract the basic authentication credentials from the request 
            // 
            if (!ExtractBasicCredentials(authorizationHeader, ref userName, ref password))
                return;
            // 
            // Validate the user credentials 
            // 
            if (!ValidateCredentials(userName, password, realm))
               return;

            // 
            // Create the user principal and associate it with the request 
            // 
            context.User = new GenericPrincipal(new GenericIdentity(userName), null);
        }

        public void IssueAuthenticationChallenge(Object source, EventArgs e)
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;

            // 
            // Issue a basic challenge if necessary 
            // 

            if (context.Response.StatusCode == HttpNotAuthorizedStatusCode)
            {
                context.Response.AddHeader(HttpWWWAuthenticateHeader, "Basic realm =\"" + Realm + "\"");
            }
        }
        #endregion

        #region Utility Methods
        protected virtual bool ValidateCredentials(String userName, String password, String realm)
        {
            // 
            //  Validate the credentials using Membership (refault provider) 
            // 
            // NOTE: Membership is commented out for clarity reasons.   
            // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
            // WARNING: DO NOT USE THE CODE BELOW IN PRODUCTION 
            // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
            // return Membership.ValidateUser(userName, password); 
            if (userName.Equals("test") && password.Equals("test"))
            {
                return true;
            }
            else 
            {
                return false;
            }    
        }
      
        protected virtual bool ExtractBasicCredentials(String authorizationHeader, ref String username, ref String password)
        {
            if ((authorizationHeader == null) || (authorizationHeader.Equals(String.Empty)))
               return false;
            String verifiedAuthorizationHeader = authorizationHeader.Trim();
            if (verifiedAuthorizationHeader.IndexOf(HttpBasicSchemeName) != 0)     
                return false;

            // get the credential payload 
            verifiedAuthorizationHeader = verifiedAuthorizationHeader.Substring(HttpBasicSchemeName.Length, verifiedAuthorizationHeader.Length - HttpBasicSchemeName.Length).Trim();
           // decode the base 64 encoded credential payload 
            byte[] credentialBase64DecodedArray = Convert.FromBase64String(verifiedAuthorizationHeader);
            UTF8Encoding encoding = new UTF8Encoding();
            String decodedAuthorizationHeader = encoding.GetString(credentialBase64DecodedArray, 0, credentialBase64DecodedArray.Length);

            // get the username, password, and realm 
            int separatorPosition = decodedAuthorizationHeader.IndexOf(HttpCredentialSeparator);

           if (separatorPosition <= 0)
              return false;
            username = decodedAuthorizationHeader.Substring(0, separatorPosition).Trim();
           password = decodedAuthorizationHeader.Substring(separatorPosition + 1, (decodedAuthorizationHeader.Length - separatorPosition - 1)).Trim();

            if (username.Equals(String.Empty) || password.Equals(String.Empty))
               return false;

           return true;
        }
        #endregion

        #region IHttpModule Members
        public void Init(HttpApplication context)
        {
            // 
            // Subscribe to the authenticate event to perform the 
            // authentication. 
            // 
            context.AuthenticateRequest += new 
                               EventHandler(this.AuthenticateUser);
            // 
            // Subscribe to the EndRequest event to issue the 
            // challenge if necessary. 
            // 
            context.EndRequest += new 
                               EventHandler(this.IssueAuthenticationChallenge);
        }
        public void Dispose()
        {
            // 
            // Do nothing here 
            // 
        }
        #endregion

    }
}

부록 B: 기본 인증 모듈에 대한 Web.config

이 구성을 애플리케이션의 루트에 web.config 파일로 저장합니다.

<configuration> 
    <system.webServer> 
      <modules> 
           <add name="MyBasicAuthenticationModule" type="IIS7Demos.BasicAuthenticationModule" /> 
      </modules> 
      <security> 
         <authentication> 
          <windowsAuthentication enabled="false"/> 
             <anonymousAuthentication enabled="false"/> 
         </authentication> 
      </security> 
    </system.webServer> 
</configuration>

부록 C: 멤버 자격 구성

ASP.NET 2.0 멤버 자격 서비스를 사용하면 애플리케이션이 대부분의 인증 및 액세스 제어 체계에 필요한 자격 증명 유효성 검사 및 사용자 관리를 신속하게 구현할 수 있습니다. 멤버 자격 증명은 애플리케이션 코드를 실제 자격 증명 저장소 구현과 격리하고 기존 자격 증명 저장소와 통합하기 위한 다양한 옵션을 제공합니다.

이 모듈 샘플의 멤버 자격을 활용하려면 ValidateCredentials 메서드 내에서 Membership.ValidateUser에 대한 호출의 주석 처리를 제거하고 애플리케이션에 대한 멤버 자격 공급자를 구성합니다. 멤버 자격 구성에 대한 자세한 내용은 멤버 자격을 사용하도록 ASP.NET 애플리케이션 구성을 참조하세요.