역할 기반 권한 부여(C#)Role-Based Authorization (C#)

Scott Mitchellby Scott Mitchell

코드 다운로드 또는 PDF 다운로드Download Code or Download PDF

이 자습서에서는 역할 프레임 워크가 사용자의 역할을 보안 컨텍스트와 연결 하는 방법을 살펴봅니다.This tutorial starts with a look at how the Roles framework associates a user's roles with his security context. 그런 다음 역할 기반 URL 권한 부여 규칙을 적용 하는 방법을 검토 합니다.It then examines how to apply role-based URL authorization rules. 이를 통해 표시 되는 데이터와 ASP.NET 페이지에서 제공 하는 기능을 변경 하기 위해 선언적이 고 프로그래밍 방식으로 사용 하는 방법을 살펴보겠습니다.Following that, we will look at using declarative and programmatic means for altering the data displayed and the functionality offered by an ASP.NET page.

소개Introduction

사용자 기반 권한 부여 자습서에서는 URL 권한 부여를 사용 하 여 특정 페이지 집합을 방문할 수 있는 사용자를 지정 하는 방법을 살펴보았습니다.In the User-Based Authorization tutorial we saw how to use URL authorization to specify what users could visit a particular set of pages. Web.config에서 약간 약간의 태그만 사용 하 여 인증 된 사용자만 페이지를 방문 하도록 ASP.NET에 지시할 수 있습니다.With just a little bit of markup in Web.config, we could instruct ASP.NET to allow only authenticated users to visit a page. 또는 사용자에 게 Tito와 Bob이 허용 되었거나 Sam을 제외한 모든 인증 된 사용자만 허용 됨을 나타낼 수 있습니다.Or we could dictate that only users Tito and Bob were allowed, or indicate that all authenticated users except for Sam were permitted.

URL 권한 부여 외에도 사용자 방문에 따라 페이지에서 제공 되는 데이터 및 표시 되는 데이터를 제어 하는 선언적 및 프로그래밍 방식의 기법을 살펴보았습니다.In addition to URL authorization, we also looked at declarative and programmatic techniques for controlling the data displayed and the functionality offered by a page based on the user visiting. 특히 현재 디렉터리의 콘텐츠를 나열 하는 페이지를 만들었습니다.In particular, we created a page that listed the contents of the current directory. 누구나이 페이지를 방문할 수 있지만 인증 된 사용자만 파일의 내용을 볼 수 있으며, 파일을 삭제할 수 있습니다.Anyone could visit this page, but only authenticated users could view the files' contents and only Tito could delete the files.

사용자를 기준으로 권한 부여 규칙을 적용 하는 것은 장부의 영향을 크게 증가 시킬 수 있습니다.Applying authorization rules on a user-by-user basis can grow into a bookkeeping nightmare. 더 쉽게 관리할 수 있는 방법은 역할 기반 권한 부여를 사용 하는 것입니다.A more maintainable approach is to use role-based authorization. 좋은 소식은 권한 부여 규칙을 적용 하는 데 필요한 도구가 사용자 계정에 대해 수행 하는 역할과 동일 하 게 잘 작동 한다는 것입니다.The good news is that the tools at our disposal for applying authorization rules work equally well with roles as they do for user accounts. URL 권한 부여 규칙은 사용자 대신 역할을 지정할 수 있습니다.URL authorization rules can specify roles instead of users. 인증 된 사용자와 익명 사용자에 대해 서로 다른 출력을 렌더링 하는 LoginView 컨트롤은 로그인 한 사용자의 역할에 따라 다른 콘텐츠를 표시 하도록 구성할 수 있습니다.The LoginView control, which renders different output for authenticated and anonymous users, can be configured to display different content based on the logged in user's roles. 및 역할 API에는 로그인 한 사용자의 역할을 결정 하는 메서드가 포함 되어 있습니다.And the Roles API includes methods for determining the logged in user's roles.

이 자습서에서는 역할 프레임 워크가 사용자의 역할을 보안 컨텍스트와 연결 하는 방법을 살펴봅니다.This tutorial starts with a look at how the Roles framework associates a user's roles with his security context. 그런 다음 역할 기반 URL 권한 부여 규칙을 적용 하는 방법을 검토 합니다.It then examines how to apply role-based URL authorization rules. 이를 통해 표시 되는 데이터와 ASP.NET 페이지에서 제공 하는 기능을 변경 하기 위해 선언적이 고 프로그래밍 방식으로 사용 하는 방법을 살펴보겠습니다.Following that, we will look at using declarative and programmatic means for altering the data displayed and the functionality offered by an ASP.NET page. 이제 시작하겠습니다.Let's get started!

사용자의 보안 컨텍스트와 역할을 연결 하는 방법 이해Understanding How Roles are Associated with a User's Security Context

요청은 ASP.NET 파이프라인에 진입할 때마다 요청자를 식별 하는 정보를 포함 하는 보안 컨텍스트와 연결 됩니다.Whenever a request enters the ASP.NET pipeline it is associated with a security context, which includes information identifying the requestor. 폼 인증을 사용 하는 경우 인증 티켓이 id 토큰으로 사용 됩니다.When using forms authentication, an authentication ticket is used as an identity token. 폼 인증 폼 인증 구성 및 고급 토픽 자습서의 개요에서 설명한 것 처럼 FormsAuthenticationModuleAuthenticateRequest 이벤트중에 수행 되는 요청자의 id를 확인 합니다.As we discussed in the An Overview of Forms Authentication and Forms Authentication Configuration and Advanced Topics tutorials, the FormsAuthenticationModule is responsible for determining the identity of the requestor, which it does during the AuthenticateRequest event.

만료 되지 않은 유효한 인증 티켓이 발견 되 면 FormsAuthenticationModule는 요청자의 id를 확인 하기 위해이를 디코딩합니다.If a valid, non-expired authentication ticket is found, the FormsAuthenticationModule decodes it to ascertain the requestor's identity. GenericPrincipal 개체를 만들고이 개체를 HttpContext.User 개체에 할당 합니다.It creates a new GenericPrincipal object and assigns this to the HttpContext.User object. GenericPrincipal와 같은 보안 주체의 목적은 인증 된 사용자의 이름 및 해당 사용자가 속한 역할을 식별 하는 것입니다.The purpose of a principal, like GenericPrincipal, is to identify the authenticated user's name and what roles she belong to. 이는 모든 보안 주체 개체에 Identity 속성과 IsInRole(roleName) 메서드가 있다는 사실에 의해 명백 합니다.This purpose is evident by the fact that all principal objects have an Identity property and an IsInRole(roleName) method. 그러나 FormsAuthenticationModule는 역할 정보를 기록 하는 데 관심이 없으며, 만든 GenericPrincipal 개체는 역할을 지정 하지 않습니다.The FormsAuthenticationModule, however, is not interested in recording role information and the GenericPrincipal object it creates does not specify any roles.

역할 프레임 워크를 사용 하는 경우 RoleManagerModule HTTP 모듈이 FormsAuthenticationModule 후에의 단계를 수행 하 고 PostAuthenticateRequest 이벤트중에 인증 된 사용자의 역할을 식별 합니다 .이 이벤트는 AuthenticateRequest 이벤트 후에 발생 합니다.If the Roles framework is enabled, the RoleManagerModule HTTP Module steps in after the FormsAuthenticationModule and identifies the authenticated user's roles during the PostAuthenticateRequest event, which fires after the AuthenticateRequest event. 요청을 인증 된 사용자에서 보낸 경우 RoleManagerModule FormsAuthenticationModule에서 만든 GenericPrincipal 개체를 덮어쓰고 RolePrincipal 개체로바꿉니다.If the request is from an authenticated user, the RoleManagerModule overwrites the GenericPrincipal object created by the FormsAuthenticationModule and replaces it with a RolePrincipal object. RolePrincipal 클래스는 역할 API를 사용 하 여 사용자가 속한 역할을 결정 합니다.The RolePrincipal class uses the Roles API to determine what roles the user belongs to.

그림 1에서는 폼 인증 및 역할 프레임 워크를 사용할 때 ASP.NET 파이프라인 워크플로를 보여 줍니다.Figure 1 depicts the ASP.NET pipeline workflow when using forms authentication and the Roles framework. FormsAuthenticationModule 먼저 실행 되 고, 사용자가 인증 티켓을 통해 사용자를 식별 하 고, 새 GenericPrincipal 개체를 만듭니다.The FormsAuthenticationModule executes first, identifies the user via her authentication ticket, and creates a new GenericPrincipal object. 그런 다음 RoleManagerModule는의 단계를 수행 하 고 GenericPrincipal 개체를 RolePrincipal 개체로 덮어씁니다.Next, the RoleManagerModule steps in and overwrites the GenericPrincipal object with a RolePrincipal object.

익명 사용자가 사이트를 방문 하는 경우 FormsAuthenticationModule 또는 RoleManagerModule는 주 개체를 만듭니다.If an anonymous user visits the site, neither the FormsAuthenticationModule nor the RoleManagerModule creates a principal object.

폼 인증 및 역할 프레임 워크를 사용 하는 경우 인증 된 사용자에 대 한 ASP.NET 파이프라인 이벤트를 합니다.The ASP.NET Pipeline Events for an Authenticated User When Using Forms Authentication and the Roles Framework

그림 1: 폼 인증 및 역할 프레임 워크를 사용 하는 경우 인증 된 사용자에 대 한 ASP.NET 파이프라인 이벤트 (전체 크기 이미지를 보려면 클릭)Figure 1: The ASP.NET Pipeline Events for an Authenticated User When Using Forms Authentication and the Roles Framework (Click to view full-size image)

RolePrincipal 개체의 IsInRole(roleName) 메서드는 Roles.GetRolesForUser를 호출 하 여 사용자가 roleName의 멤버 인지 여부를 확인 하기 위해 사용자에 대 한 역할을 가져옵니다.The RolePrincipal object's IsInRole(roleName) method calls Roles.GetRolesForUser to get the roles for the user in order to determine whether the user is a member of roleName. SqlRoleProvider사용 하는 경우 역할 저장소 데이터베이스에 대 한 쿼리가 생성 됩니다.When using the SqlRoleProvider, this results in a query to the role store database. 역할 기반 URL 권한 부여 규칙을 사용 하는 경우 역할 기반 URL 권한 부여 규칙에 의해 보호 되는 페이지에 대 한 모든 요청에 대해 RolePrincipalIsInRole 메서드가 호출 됩니다.When using role-based URL authorization rules the RolePrincipal's IsInRole method will be called on every request to a page that is protected by the role-based URL authorization rules. 모든 요청에 대해 데이터베이스에서 역할 정보를 조회 해야 하는 대신, 역할 프레임 워크에는 쿠키에 사용자의 역할을 캐시 하는 옵션이 포함 되어 있습니다.Rather than have to lookup the role information in the database on every request, the Roles framework includes an option to cache the user's roles in a cookie.

역할 프레임 워크가 사용자의 역할을 쿠키에 캐시 하도록 구성 된 경우 RoleManagerModule ASP.NET 파이프라인의 EndRequest 이벤트중에 쿠키를 만듭니다.If the Roles framework is configured to cache the user's roles in a cookie, the RoleManagerModule creates the cookie during the ASP.NET pipeline's EndRequest event. 이 쿠키는 PostAuthenticateRequest의 후속 요청에 사용 됩니다 .이는 RolePrincipal 개체를 만든 시간입니다.This cookie is used in subsequent requests in the PostAuthenticateRequest, which is when the RolePrincipal object is created. 쿠키가 유효 하 고 만료 되지 않은 경우에는 쿠키의 데이터가 구문 분석 되 고 사용자의 역할을 채우는 데 사용 되므로 Roles 클래스를 호출 하 여 사용자의 역할을 결정 하지 않아도 RolePrincipal 저장 됩니다.If the cookie is valid and has not expired, the data in the cookie is parsed and used to populate the user's roles, thereby saving the RolePrincipal from having to make a call to the Roles class to determine the user's roles. 그림 2에서는이 워크플로를 보여 줍니다.Figure 2 depicts this workflow.

사용자의 역할 정보를 쿠키에 저장 하 여 성능을 향상 시킬 수 있습니다.The User's Role Information Can Be Stored in a Cookie to Improve Performance

그림 2: 사용자의 역할 정보를 쿠키에 저장 하 여 성능을 향상 시킬 수 있습니다 (전체 크기 이미지를 보려면 클릭).Figure 2: The User's Role Information Can Be Stored in a Cookie to Improve Performance (Click to view full-size image)

기본적으로 역할 캐시 쿠키 메커니즘은 사용 하지 않도록 설정 되어 있습니다.By default, the role cache cookie mechanism is disabled. Web.config에서 <roleManager> 구성 태그를 통해 사용 하도록 설정할 수 있습니다.It can be enabled through the <roleManager> configuration markup in Web.config. <roleManager> 요소 를 사용 하 여 역할 만들기 및 관리 자습서에서 역할 공급자를 지정 하는 방법을 설명 했으므로 응용 프로그램의 Web.config 파일에이 요소가 이미 있어야 합니다.We discussed using the <roleManager> element to specify Role providers in the Creating and Managing Roles tutorial, so you should already have this element in your application's Web.config file. 역할 캐시 쿠키 설정은 <roleManager> 요소의 특성으로 지정 되며 표 1에 요약 되어 있습니다.The role cache cookie settings are specified as attributes of the <roleManager> element, and are summarized in Table 1.

Note

표 1에 나열 된 구성 설정은 결과 역할 캐시 쿠키의 속성을 지정 합니다.The configuration settings listed in Table 1 specify the properties of the resulting role cache cookie. 쿠키, 작동 방법 및 다양 한 속성에 대 한 자세한 내용은 이 쿠키 자습서를 참조 하세요.For more information on cookies, how they work, and their various properties, read this Cookies tutorial.

속성Property 설명Description
cacheRolesInCookie 쿠키 캐싱이 사용 되는지 여부를 나타내는 부울 값입니다.A Boolean value that indicates whether cookie caching is used. 기본값은 false입니다.Defaults to false.
cookieName 역할 캐시 쿠키의 이름입니다.The name of the role cache cookie. 기본값은 "입니다. 역할을 합니다. "The default value is ".ASPXROLES".
cookiePath 역할 이름 쿠키의 경로입니다.The path for the roles name cookie. 개발자는 path 특성을 사용 하 여 쿠키 범위를 특정 디렉터리 계층으로 제한할 수 있습니다.The path attribute enables a developer to limit the scope of a cookie to a particular directory hierarchy. 기본값은 "/" 이며,이는 브라우저에서 도메인에 대 한 모든 요청에 인증 티켓 쿠키를 보내도록 알려 줍니다.The default value is "/", which informs the browser to send the authentication ticket cookie to any request made to the domain.
cookieProtection 역할 캐시 쿠키를 보호 하는 데 사용 되는 기술을 나타냅니다.Indicates what techniques are used to protect the role cache cookie. 허용 되는 값은 All (기본값)입니다. Encryption; None; 및를 Validation합니다.The allowable values are: All (the default); Encryption; None; and Validation. 이러한 보호 수준에 대 한 자세한 내용은 Forms 인증 구성 및 고급 항목 자습서의 3 단계를 다시 참조 하세요.Refer back to Step 3 of the Forms Authentication Configuration and Advanced Topics tutorial for more information on these protection levels.
cookieRequireSSL 인증 쿠키를 전송 하는 데 SSL 연결이 필요한 지 여부를 나타내는 부울 값입니다.A Boolean value that indicates whether an SSL connection is required to transmit the authentication cookie. 기본값은 false입니다.The default value is false.
cookieSlidingExpiration 단일 세션 중에 사용자가 사이트를 방문할 때마다 쿠키의 시간 제한이 다시 설정 되는지 여부를 나타내는 부울 값입니다.A Boolean value that indicates whether the cookie's timeout is reset each time the user visits the site during a single session. 기본값은 false입니다.The default value is false. 이 값은 createPersistentCookietrue으로 설정 된 경우에만 관련이 있습니다.This value is only pertinent when createPersistentCookie is set to true.
cookieTimeout 인증 티켓 쿠키가 만료 되는 시간 (분)을 지정 합니다.Specifies the time, in minutes, after which the authentication ticket cookie expires. 기본값은 30입니다.The default value is 30. 이 값은 createPersistentCookietrue으로 설정 된 경우에만 관련이 있습니다.This value is only pertinent when createPersistentCookie is set to true.
createPersistentCookie 역할 캐시 쿠키가 세션 쿠키 인지 아니면 영구 쿠키 인지를 지정 하는 부울 값입니다.A Boolean value that specifies whether the role cache cookie is a session cookie or persistent cookie. false (기본값) 이면 브라우저를 닫을 때 삭제 되는 세션 쿠키가 사용 됩니다.If false (the default), a session cookie is used, which is deleted when the browser is closed. true경우 영구 쿠키가 사용 됩니다. cookieSlidingExpiration값에 따라이 값이 생성 된 후 또는 이전에 방문한 후의 시간 (분) cookieTimeout 만료 됩니다.If true, a persistent cookie is used; it expires cookieTimeout number of minutes after it has been created or after the previous visit, depending on the value of cookieSlidingExpiration.
domain 쿠키의 도메인 값을 지정 합니다.Specifies the cookie's domain value. 기본값은 빈 문자열입니다 .이 문자열을 사용 하면 브라우저가 발급 된 도메인 (예: www.yourdomain.com)을 사용 합니다.The default value is an empty string, which causes the browser to use the domain from which it was issued (such as www.yourdomain.com). 이 경우 admin.yourdomain.com와 같은 하위 도메인에 대 한 요청을 만들 때 쿠키가 전송 되지 않습니다.In this case, the cookie will not be sent when making requests to subdomains, such as admin.yourdomain.com. 모든 하위 도메인에 쿠키를 전달 하려면 domain 특성을 "yourdomain.com"로 설정 하 여 사용자 지정 해야 합니다.If you want the cookie to be passed to all subdomains you need to customize the domain attribute, setting it to "yourdomain.com".
maxCachedResults 쿠키에 캐시 되는 최대 역할 이름 수를 지정 합니다.Specifies the maximum number of role names that are cached in the cookie. 기본값은 25입니다.The default is 25. RoleManagerModulemaxCachedResults 역할에 속하는 사용자에 대 한 쿠키를 만들지 않습니다.The RoleManagerModule does not create a cookie for users that belong to more than maxCachedResults roles. 따라서 RolePrincipal 개체의 IsInRole 메서드에서는 Roles 클래스를 사용 하 여 사용자의 역할을 결정 합니다.Consequently, the RolePrincipal object's IsInRole method will use the Roles class to determine the user's roles. maxCachedResults 존재 하는 이유는 많은 사용자 에이전트가 4096 바이트 보다 큰 쿠키를 허용 하지 않기 때문입니다.The reason maxCachedResults exists is because many user agents do not permit cookies larger than 4,096 bytes. 따라서이 캡은 이러한 크기 제한을 초과 하는 가능성을 줄이기 위한 것입니다.So this cap is meant to reduce the likelihood of exceeding this size limitation. 역할 이름이 매우 긴 경우 더 작은 maxCachedResults 값을 지정 하는 것을 고려할 수 있습니다. contrariwise 역할 이름이 매우 짧은 경우이 값을 늘릴 수 있습니다.If you have extremely long role names, you may want to consider specifying a smaller maxCachedResults value; contrariwise, if you have extremely short role names, you can probably increase this value.

표 1: 역할 캐시 쿠키 구성 옵션Table 1: The Role Cache Cookie Configuration Options

비영구 역할 캐시 쿠키를 사용 하도록 응용 프로그램을 구성 해 보겠습니다.Let's configure our application to use non-persistent role cache cookies. 이 작업을 수행 하려면 Web.config에서 <roleManager> 요소를 업데이트 하 여 다음과 같은 쿠키 관련 특성을 포함 합니다.To accomplish this, update the <roleManager> element in Web.config to include the following cookie-related attributes:

<roleManager enabled="true"    
          defaultProvider="SecurityTutorialsSqlRoleProvider"    
          cacheRolesInCookie="true"    
          createPersistentCookie="false"    
          cookieProtection="All">    

     <providers>    
     ...    
     </providers>    
</roleManager>

cacheRolesInCookie, createPersistentCookiecookieProtection의 세 가지 특성을 추가 하 여 <roleManager> 요소를 업데이트 했습니다.I updated the <roleManager> element by adding three attributes: cacheRolesInCookie, createPersistentCookie, and cookieProtection. cacheRolesInCookietrue로 설정 하면 RoleManagerModule에서 각 요청에 대 한 사용자의 역할 정보를 조회 하지 않고 쿠키에 사용자 역할을 자동으로 캐시 합니다.By setting cacheRolesInCookie to true, the RoleManagerModule will now automatically cache the user's roles in a cookie rather than having to lookup the user's role information on each request. createPersistentCookiecookieProtection 특성을 명시적으로 falseAll로 각각 설정 합니다.I explicitly set the createPersistentCookie and cookieProtection attributes to false and All, respectively. 기술적으로는 이러한 특성에 대 한 값을 기본값에 할당 했기 때문에 이러한 특성에 대 한 값을 지정할 필요가 없지만, 영구 쿠키를 사용 하지 않고 쿠키를 암호화 하 고 유효성을 검사 하는 것을 명시적으로 명확 하 게 하려면 여기에 입력 합니다.Technically, I didn't need to specify values for these attributes since I just assigned them to their default values, but I put them here to make it explicitly clear that I am not using persistent cookies and that the cookie is both encrypted and validated.

이제 모든 작업을 마쳤습니다.That's all there is to it! 예측이 역할 프레임 워크는 사용자의 역할을 쿠키에 캐시 합니다.Henceforth, the Roles framework will cache the users' roles in cookies. 사용자의 브라우저에서 쿠키를 지원 하지 않거나 쿠키를 삭제 하거나 손실 하는 경우에는 큰 문제가 없습니다. RolePrincipal 개체는 쿠키를 사용 하지 않는 경우 (또는 유효 하지 않거나 만료 된 경우)에만 Roles 클래스를 사용 합니다.If the user's browser does not support cookies, or if their cookies are deleted or lost, somehow, it's no big deal – the RolePrincipal object will simply use the Roles class in the case that no cookie (or an invalid or expired one) is available.

Note

Microsoft의 패턴 & 영구 역할 캐시 쿠키를 사용 하는 것은 권장 되지 않습니다.Microsoft's Patterns & Practices group discourages using persistent role cache cookies. 역할 캐시 쿠키의 소유는 역할 멤버 자격을 증명 하는 데 충분 하므로 해커가 유효한 사용자의 쿠키에 대 한 액세스 권한을 얻을 수 있으면 해당 사용자를 가장할 수 있습니다.Since possession of the role cache cookie is sufficient to prove role membership, if a hacker can somehow gain access to a valid user's cookie he can impersonate that user. 쿠키가 사용자의 브라우저에서 지속 되 면 이러한 상황이 발생할 가능성이 높아집니다.The likelihood of this happening increases if the cookie is persisted on the user's browser. 이 보안 권장 사항 및 기타 보안 고려 사항에 대 한 자세한 내용은 ASP.NET 2.0에 대 한 보안 질문 목록을참조 하세요.For more information on this security recommendation, as well as other security concerns, refer to the Security Question List for ASP.NET 2.0.

1 단계: 역할 기반 URL 권한 부여 규칙 정의Step 1: Defining Role-Based URL Authorization Rules

사용자 기반 권한 부여 자습서에서 설명 하는 것 처럼 URL 권한 부여는 사용자 또는 역할별 역할 별로 페이지 집합에 대 한 액세스를 제한 하는 수단을 제공 합니다.As discussed in the User-Based Authorization tutorial, URL authorization offers a means to restrict access to a set of pages on a user-by-user or role-by-role basis. URL 권한 부여 규칙은 <allow><deny> 자식 요소와 함께 <authorization> 요소 를 사용 하 여 Web.config에서 주석으로 처리 됩니다.The URL authorization rules are spelled out in Web.config using the <authorization> element with <allow> and <deny> child elements. 이전 자습서에서 설명한 사용자 관련 권한 부여 규칙 외에도 각 <allow><deny> 자식 요소에는 다음이 포함 될 수 있습니다.In addition to the user-related authorization rules discussed in previous tutorials, each <allow> and <deny> child element can also include:

  • 특정 역할A particular role
  • 쉼표로 구분 된 역할 목록A comma-delimited list of roles

예를 들어 URL 권한 부여 규칙은 관리자 및 감독자 역할의 사용자에 게 액세스 권한을 부여 하지만 다른 모든 사용자에 대 한 액세스를 거부 합니다.For example, the URL authorization rules grant access to those users in the Administrators and Supervisors roles, but deny access to all others:

<authorization>
     <allow roles="Administrators, Supervisors" />
     <deny users="*" />
</authorization>

위의 태그에서 <allow> 요소는 Administrators 및 감독자 역할이 허용 되는 상태를 표시 합니다. <deny> 요소는 모든 사용자가 거부 되었음을 지시 합니다.The <allow> element in the above markup states that the Administrators and Supervisors roles are allowed; the <deny> element instructs that all users are denied.

ManageRoles.aspx, UsersAndRoles.aspxCreateUserWizardWithRoles.aspx 페이지를 관리자 역할의 사용자만 액세스할 수 있도록 응용 프로그램을 구성 하 고, RoleBasedAuthorization.aspx 페이지는 모든 방문자에 게 계속 액세스할 수 있습니다.Let's configure our application so that the ManageRoles.aspx, UsersAndRoles.aspx, and CreateUserWizardWithRoles.aspx pages are only accessible to those users in the Administrators role, while the RoleBasedAuthorization.aspx page remains accessible to all visitors.

이를 수행 하려면 먼저 Roles 폴더에 Web.config 파일을 추가 합니다.To accomplish this, start by adding a Web.config file to the Roles folder.

역할 디렉터리에 web.config 파일을 추가 Add a Web.config File to the Roles directory

그림 3: Roles 디렉터리에 Web.config 파일 추가 (전체 크기 이미지를 보려면 클릭)Figure 3: Add a Web.config File to the Roles directory (Click to view full-size image)

그런 다음 Web.config에 다음 구성 태그를 추가 합니다.Next, add the following configuration markup to Web.config:

<?xml version="1.0"?>    

<configuration>    
     <system.web>    
          <authorization>    
               <allow roles="Administrators" />    
               <deny users="*"/>    
          </authorization>    

     </system.web>

     <!-- Allow all users to visit RoleBasedAuthorization.aspx -->    
     <location path="RoleBasedAuthorization.aspx">    
          <system.web>    
               <authorization>    
                    <allow users="*" />    

               </authorization>    
          </system.web>    
     </location>    
</configuration>

<system.web> 섹션의 <authorization> 요소는 Administrators 역할의 사용자만 Roles 디렉터리의 ASP.NET 리소스에 액세스할 수 있음을 나타냅니다.The <authorization> element in the <system.web> section indicates that only users in the Administrators role may access the ASP.NET resources in the Roles directory. <location> 요소는 RoleBasedAuthorization.aspx 페이지에 대 한 URL 권한 부여 규칙의 대체 집합을 정의 하 여 모든 사용자가 페이지를 방문할 수 있도록 합니다.The <location> element defines an alternate set of URL authorization rules for the RoleBasedAuthorization.aspx page, allowing all users to visit the page.

Web.config에 대 한 변경 내용을 저장 한 후 관리자 역할에 없는 사용자로 로그인 한 다음 보호 된 페이지 중 하나를 방문 하십시오.After saving your changes to Web.config, log in as a user that is not in the Administrators role and then try to visit one of the protected pages. UrlAuthorizationModule는 요청한 리소스를 방문할 권한이 없다는 것을 감지 합니다. 따라서 FormsAuthenticationModule 로그인 페이지로 리디렉션됩니다.The UrlAuthorizationModule will detect that you do not have permission to visit the requested resource; consequently, the FormsAuthenticationModule will redirect you to the login page. 그러면 로그인 페이지가 UnauthorizedAccess.aspx 페이지로 리디렉션됩니다 (그림 4 참조).The login page will then redirect you to the UnauthorizedAccess.aspx page (see Figure 4). 사용자 기반 권한 부여 자습서의 2 단계에서 로그인 페이지에 추가 된 코드 때문에 로그인 페이지의이 최종 리디렉션은 UnauthorizedAccess.aspx 발생 합니다.This final redirect from the login page to UnauthorizedAccess.aspx occurs because of code we added to the login page in Step 2 of the User-Based Authorization tutorial. 특히,이 매개 변수는 사용자가 볼 권한이 없는 페이지를 보려고 시도한 후에 사용자가 로그인 페이지에 도착 했음을 나타내므로 로그인 페이지는 모든 인증 된 사용자를 ReturnUrl UnauthorizedAccess.aspx으로 자동 리디렉션합니다.In particular, the login page automatically redirects any authenticated user to UnauthorizedAccess.aspx if the querystring contains a ReturnUrl parameter, as this parameter indicates that the user arrived at the login page after attempting to view a page he was not authorized to view.

관리자 역할의 사용자만 보호 된 페이지를 볼 수 있습니다.Only Users in the Administrators Role Can View the Protected Pages

그림 4: 관리자 역할의 사용자만 보호 된 페이지를 볼 수 있음 (전체 크기 이미지를 보려면 클릭)Figure 4: Only Users in the Administrators Role Can View the Protected Pages (Click to view full-size image)

로그 오프 한 다음 관리자 역할에 있는 사용자로 로그인 합니다.Log off and then log in as a user that is in the Administrators role. 이제 세 개의 보호 된 페이지를 볼 수 있습니다.Now you should be able to view the three protected pages.

Tito는 관리자 역할에 있기 때문에 UsersAndRoles 페이지를 방문할 수 있습니다.Tito Can Visit the UsersAndRoles.aspx Page Because He is in the Administrators Role

그림 5: UsersAndRoles.aspx 페이지를 방문 하 여 관리자 역할을 할 수 있습니다 (전체 크기 이미지를 보려면 클릭).Figure 5: Tito Can Visit the UsersAndRoles.aspx Page Because He is in the Administrators Role (Click to view full-size image)

Note

역할 또는 사용자에 대해 URL 권한 부여 규칙을 지정 하는 경우 규칙은 위에서 아래로 한 번에 하나씩 분석 된다는 점을 명심 해야 합니다.When specifying URL authorization rules – for roles or users – it is important to keep in mind that the rules are analyzed one at a time, from the top down. 일치 항목이 발견 되는 즉시 사용자에 게 일치 항목을 <allow> 또는 <deny> 요소에서 찾을 수 있는지에 따라 액세스 권한이 부여 되거나 거부 됩니다.As soon as a match is found, the user is granted or denied access, depending on if the match was found in an <allow> or <deny> element. 일치 항목을 찾을 수 없는 경우 사용자에 게 액세스 권한이 부여 됩니다.If no match is found, the user is granted access. 따라서 하나 이상의 사용자 계정에 대 한 액세스를 제한 하려는 경우 URL 권한 부여 구성에서 <deny> 요소를 마지막 요소로 사용 해야 합니다.Consequently, if you want to restrict access to one or more user accounts, it is imperative that you use a <deny> element as the last element in the URL authorization configuration. URL 권한 부여 규칙에<deny>요소가 포함 되지 않은 경우 모든 사용자에 게 액세스 권한이 부여 됩니다.If your URL authorization rules do not include a<deny>element, all users will be granted access. URL 권한 부여 규칙을 분석 하는 방법에 대 한 자세한 내용은 사용자 기반 권한 부여 자습서의 "UrlAuthorizationModule 권한 부여 규칙을 사용 하 여 액세스 권한을 부여 하거나 거부 하는 방법" 섹션을 참조 하세요.For a more thorough discussion on how the URL authorization rules are analyzed, refer back to the "A Look at How the UrlAuthorizationModule Uses the Authorization Rules to Grant or Deny Access" section of the User-Based Authorization tutorial.

2 단계: 현재 로그인 한 사용자의 역할을 기준으로 기능 제한Step 2: Limiting Functionality Based On the Currently Logged In User's Roles

URL 권한 부여를 사용 하면 허용 되는 id와 특정 페이지 (또는 폴더 및 해당 하위 폴더의 모든 페이지)를 볼 때 거부 된 id를 명시 하는 정교 하지 않은 권한 부여 규칙을 쉽게 지정할 수 있습니다.URL authorization makes it easy to specify coarse authorization rules that state what identities are permitted and which ones are denied from viewing a particular page (or all pages in a folder and its subfolders). 그러나 특정 한 경우에는 모든 사용자가 페이지를 방문 하도록 허용할 수 있지만 방문 사용자의 역할에 따라 페이지의 기능을 제한 하는 것이 좋습니다.However, in certain cases we may want to allow all users to visit a page, but limit the page's functionality based on the visiting user's roles. 이 경우 사용자의 역할에 따라 데이터를 표시 하거나 숨기 거 나 특정 역할에 속한 사용자에 게 추가 기능을 제공할 수 있습니다.This may entail showing or hiding data based on the user's role, or offering additional functionality to users that belong to a particular role.

이러한 미세 수준 역할 기반 권한 부여 규칙은 선언적으로 또는 프로그래밍 방식으로 구현 하거나 둘 중 일부를 조합 하 여 구현할 수 있습니다.Such fine grain role-based authorization rules can be implemented either declaratively or programmatically (or through some combination of the two). 다음 섹션에서는 LoginView 컨트롤을 통해 선언적 미세 인증을 구현 하는 방법을 알아봅니다.In the next section we will see how to implement declarative fine grain authorization via the LoginView control. 다음에는 프로그래밍 방식으로 살펴볼 것입니다.Following that, we will explore programmatic techniques. 그러나 세분화 된 권한 부여 규칙을 적용 하는 방법에 대 한 자세한 내용은 먼저 해당 기능이 방문 하는 사용자의 역할에 따라 달라 지는 페이지를 만들어야 합니다.Before we can look at applying fine grain authorization rules, however, we first need to create a page whose functionality depends on the role of the user visiting it.

GridView에서 시스템의 모든 사용자 계정을 나열 하는 페이지를 만들어 보겠습니다.Let's create a page that lists all of the user accounts in the system in a GridView. GridView에는 각 사용자의 사용자 이름, 전자 메일 주소, 마지막 로그인 날짜 및 사용자에 대 한 설명이 포함 됩니다.The GridView will include each user's username, email address, last login date, and comments about the user. 각 사용자 정보를 표시 하는 것 외에도 GridView에는 편집 및 삭제 기능이 포함 됩니다.In addition to displaying each user's information, the GridView will include edit and delete capabilities. 처음에는 모든 사용자가 사용할 수 있는 편집 및 삭제 기능을 사용 하 여이 페이지를 만들게 됩니다.We will initially create this page with the edit and delete functionality available to all users. "LoginView 컨트롤 사용" 및 "프로그래밍 방식으로 기능 제한" 섹션에서 방문 사용자의 역할에 따라 이러한 기능을 사용 하거나 사용 하지 않도록 설정 하는 방법을 확인할 수 있습니다.In the "Using the LoginView Control" and "Programmatically Limiting Functionality" sections we will see how to enable or disable these features based on the visiting user's role.

Note

빌드 하려는 ASP.NET 페이지에서 GridView 컨트롤을 사용 하 여 사용자 계정을 표시 합니다.The ASP.NET page we are about to build uses a GridView control to display the user accounts. 이 자습서 시리즈는 폼 인증, 권한 부여, 사용자 계정 및 역할에 중점을 둘 수 있으므로 GridView 컨트롤의 내부 작업에 대해 너무 많은 시간을 할애 하지 않으려고 합니다.Since this tutorial series focuses on forms authentication, authorization, user accounts, and roles, I do not want to spend too much time discussing the inner workings of the GridView control. 이 자습서에서는이 페이지를 설정 하는 방법에 대 한 구체적인 단계별 지침을 제공 하지만 특정 항목을 선택 하는 이유와 렌더링 된 출력에 적용 되는 특정 속성에 대 한 자세한 내용은 설명 하지 않습니다.While this tutorial provides specific step-by-step instructions for setting up this page, it does not delve into the details of why certain choices were made, or what effect particular properties have on the rendered output. GridView 컨트롤을 철저 하 게 검사 하려면 ASP.NET 2.0 자습서 시리즈 의 데이터로 작업 을 확인 하세요.For a thorough examination of the GridView control, check out my Working with Data in ASP.NET 2.0 tutorial series.

먼저 Roles 폴더에서 RoleBasedAuthorization.aspx 페이지를 엽니다.Start by opening the RoleBasedAuthorization.aspx page in the Roles folder. 페이지에서 GridView를 디자이너로 끌어 IDUserGrid로 설정 합니다.Drag a GridView from the page onto the Designer and set its ID to UserGrid. 잠시 후 Membership.GetAllUsers 메서드를 호출 하 고 결과 MembershipUserCollection 개체를 GridView에 바인딩하는 코드를 작성 합니다.In a moment we will write code that calls the Membership.GetAllUsers method and binds the resulting MembershipUserCollection object to the GridView. MembershipUserCollection는 시스템의 각 사용자 계정에 대 한 MembershipUser 개체를 포함 합니다. MembershipUser 개체에는 UserName, Email, LastLoginDate등의 속성이 있습니다.The MembershipUserCollection contains a MembershipUser object for each user account in the system; MembershipUser objects have properties like UserName, Email, LastLoginDate, and so forth.

사용자 계정을 표에 바인딩하는 코드를 작성 하기 전에 먼저 GridView의 필드를 정의 해 보겠습니다.Before we write the code that binds the user accounts to the grid, let's first define the GridView's fields. GridView의 스마트 태그에서 "열 편집" 링크를 클릭 하 여 필드 대화 상자를 시작 합니다 (그림 6 참조).From the GridView's Smart Tag, click the "Edit Columns" link to launch the Fields dialog box (see Figure 6). 여기에서 왼쪽 아래에 있는 "필드 자동 생성" 확인란의 선택을 취소 합니다.From here, uncheck the "Auto-generate fields" checkbox in the lower left corner. 이 GridView에서 편집 및 삭제 기능을 포함 하려고 하므로 CommandField를 추가 하 고 해당 ShowEditButtonShowDeleteButton 속성을 True로 설정 합니다.Since we want this GridView to include editing and deleting capabilities, add a CommandField and set its ShowEditButton and ShowDeleteButton properties to True. 다음으로 UserName, Email, LastLoginDateComment 속성을 표시 하는 네 개의 필드를 추가 합니다.Next, add four fields for displaying the UserName, Email, LastLoginDate, and Comment properties. 편집 가능한 두 필드 (EmailComment)에 대해 두 개의 읽기 전용 속성 (UserNameLastLoginDate) 및 템플릿 필드에 대해 BoundField를 사용 합니다.Use a BoundField for the two read-only properties (UserName and LastLoginDate) and TemplateFields for the two editable fields (Email and Comment).

첫 번째 BoundField에 UserName 속성이 표시 되도록 합니다. HeaderTextDataField 속성을 "UserName"으로 설정 합니다.Have the first BoundField display the UserName property; set its HeaderText and DataField properties to "UserName". 이 필드는 편집할 수 없으므로 ReadOnly 속성을 True로 설정 합니다.This field will not be editable, so set its ReadOnly property to True. HeaderText를 "마지막 로그인"으로 설정 하 고 해당 DataField를 "LastLoginDate"로 설정 하 여 LastLoginDate BoundField를 구성 합니다.Configure the LastLoginDate BoundField by setting its HeaderText to "Last Login" and its DataField to "LastLoginDate". 날짜 및 시간 대신 날짜만 표시 되도록이 BoundField의 출력 형식을 지정 하겠습니다.Let's format the output of this BoundField so that just the date is displayed (instead of the date and time). 이를 수행 하려면이 BoundField의 HtmlEncode 속성을 False로 설정 하 고 DataFormatString 속성을 "{0:d}"로 설정 합니다.To accomplish this, set this BoundField's HtmlEncode property to False and its DataFormatString property to "{0:d}". 또한 ReadOnly 속성을 True로 설정 합니다.Also set the ReadOnly property to True.

두 개의 템플릿 필드의 HeaderText 속성을 "Email" 및 "Comment"로 설정 합니다.Set the HeaderText properties of the two TemplateFields to "Email" and "Comment".

필드 대화 상자를 통해 GridView의 필드를 구성할 수 .The GridView's Fields Can Be Configured Through the Fields Dialog Box

그림 6: 필드 대화 상자를 통해 GridView의 필드를 구성할 수 있습니다 (전체 크기 이미지를 보려면 클릭).Figure 6: The GridView's Fields Can Be Configured Through the Fields Dialog Box (Click to view full-size image)

이제 "전자 메일" 및 "주석" 템플릿 필드에 대 한 ItemTemplateEditItemTemplate를 정의 해야 합니다.We now need to define the ItemTemplate and EditItemTemplate for the "Email" and "Comment" TemplateFields. ItemTemplate에 Label 웹 컨트롤을 추가 하 고 Text 속성을 EmailComment 속성에 각각 바인딩합니다.Add a Label Web control to each of the ItemTemplate s and bind their Text properties to the Email and Comment properties, respectively.

"Email" Templatefield로 변환의 경우 Email 이라는 텍스트 상자를 EditItemTemplate에 추가 하 고 양방향 데이터 바인딩을 사용 하 여 Text 속성을 Email 속성에 바인딩합니다.For the "Email" TemplateField, add a TextBox named Email to its EditItemTemplate and bind its Text property to the Email property using two-way databinding. 전자 메일 속성을 편집 하는 방문자가 유효한 전자 메일 주소를 입력 했는지 확인 하려면 RequiredFieldValidator 및 RegularExpressionValidator을 EditItemTemplate에 추가 합니다.Add a RequiredFieldValidator and RegularExpressionValidator to the EditItemTemplate to ensure that a visitor editing the Email property has entered a valid email address. "Comment" Templatefield로 변환 EditItemTemplateComment 라는 여러 줄 텍스트 상자를 추가 합니다.For the "Comment" TemplateField, add a multi-line TextBox named Comment to its EditItemTemplate. 텍스트 상자의 ColumnsRows 속성을 각각 40 및 4로 설정 하 고, 양방향 데이터 바인딩을 사용 하 여 Text 속성을 Comment 속성에 바인딩합니다.Set the TextBox's Columns and Rows properties to 40 and 4, respectively, and then bind its Text property to the Comment property using two-way databinding.

이러한 템플릿 필드를 구성한 후에는 해당 선언적 태그가 다음과 같이 표시 됩니다.After configuring these TemplateFields, their declarative markup should look similar to the following:

<asp:TemplateField HeaderText="Email">    
     <ItemTemplate>    
          <asp:Label runat="server" ID="Label1" Text='<%# Eval("Email") %>'></asp:Label>    

     </ItemTemplate>    
     <EditItemTemplate>    
          <asp:TextBox runat="server" ID="Email" Text='<%# Bind("Email") %>'></asp:TextBox>    

          <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server"    
               ControlToValidate="Email" Display="Dynamic"    
               ErrorMessage="You must provide an email address." 
               SetFocusOnError="True">*</asp:RequiredFieldValidator>    

          <asp:RegularExpressionValidator ID="RegularExpressionValidator1" runat="server"    
               ControlToValidate="Email" Display="Dynamic"    
               ErrorMessage="The email address you have entered is not valid. Please fix 
               this and try again."    
               SetFocusOnError="True"    

               ValidationExpression="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*">*
          </asp:RegularExpressionValidator>    
     </EditItemTemplate>    
</asp:TemplateField>

<asp:TemplateField HeaderText="Comment">    
     <ItemTemplate>    
          <asp:Label runat="server" ID="Label2" Text='<%# Eval("Comment") %>'></asp:Label>    

     </ItemTemplate>    
     <EditItemTemplate>    
          <asp:TextBox runat="server" ID="Comment" TextMode="MultiLine"
               Columns="40" Rows="4" Text='<%# Bind("Comment") %>'>

          </asp:TextBox>    
     </EditItemTemplate>    
</asp:TemplateField>

사용자 계정을 편집 하거나 삭제 하는 경우 해당 사용자의 UserName 속성 값을 알고 있어야 합니다.When editing or deleting a user account we will need to know that user's UserName property value. Gridview의 DataKeys 컬렉션을 통해이 정보를 사용할 수 있도록 GridView의 DataKeyNames 속성을 "UserName"으로 설정 합니다.Set the GridView's DataKeyNames property to "UserName" so that this information is available through the GridView's DataKeys collection.

마지막으로 페이지에 ValidationSummary 컨트롤을 추가 하 고 해당 ShowMessageBox 속성을 True로 설정 하 고 ShowSummary 속성을 False로 설정 합니다.Finally, add a ValidationSummary control to the page and set its ShowMessageBox property to True and its ShowSummary property to False. 이러한 설정을 사용 하면 사용자가 누락 되거나 잘못 된 전자 메일 주소를 사용 하 여 사용자 계정을 편집 하려고 하는 경우 ValidationSummary가 클라이언트 쪽 경고를 표시 합니다.With these settings, the ValidationSummary will display a client-side alert if the user attempts to edit a user account with a missing or invalid email address.

<asp:ValidationSummary ID="ValidationSummary1"
               runat="server"
               ShowMessageBox="True"
               ShowSummary="False" />

이제이 페이지의 선언적 태그를 완료 했습니다.We have now completed this page's declarative markup. 다음 작업은 사용자 계정 집합을 GridView에 바인딩하는 것입니다.Our next task is to bind the set of user accounts to the GridView. Membership.GetAllUsers에서 반환 하는 MembershipUserCollectionUserGrid GridView에 바인딩하는 RoleBasedAuthorization.aspx 페이지의 코드 숨김이 클래스에 BindUserGrid 라는 메서드를 추가 합니다.Add a method named BindUserGrid to the RoleBasedAuthorization.aspx page's code-behind class that binds the MembershipUserCollection returned by Membership.GetAllUsers to the UserGrid GridView. 첫 번째 페이지의 Page_Load 이벤트 처리기에서이 메서드를 호출 합니다.Call this method from the Page_Load event handler on the first page visit.

protected void Page_Load(object sender, EventArgs e)    
{    
     if (!Page.IsPostBack)    
          BindUserGrid();    
}

private void BindUserGrid()    
{    
     MembershipUserCollection allUsers = Membership.GetAllUsers();    
     UserGrid.DataSource = allUsers;    
     UserGrid.DataBind();    
}

이 코드가 준비 되 면 브라우저를 통해 페이지를 방문 하세요.With this code in place, visit the page through a browser. 그림 7에 표시 된 것 처럼 시스템의 각 사용자 계정에 대 한 정보를 나열 하는 GridView가 표시 되어야 합니다.As Figure 7 shows, you should see a GridView listing information about each user account in the system.

UserGrid GridView 시스템의 각 사용자에 대 한 정보를 나열 합니다.The UserGrid GridView Lists Information About Each User in the System

그림 7: GridView UserGrid 시스템의 각 사용자에 대 한 정보 나열 (전체 크기 이미지를 보려면 클릭)Figure 7: The UserGrid GridView Lists Information About Each User in the System (Click to view full-size image)

Note

UserGrid GridView는 비페이징 인터페이스의 모든 사용자를 나열 합니다.The UserGrid GridView lists all of the users in a non-paged interface. 이 간단한 그리드 인터페이스는 수십 명 이상의 사용자가 있는 시나리오에 적합 하지 않습니다.This simple grid interface is not suitable for scenarios where there are several dozen or more users. 한 가지 옵션은 페이징을 사용 하도록 GridView를 구성 하는 것입니다.One option is to configure the GridView to enable paging. Membership.GetAllUsers 메서드에는 두 개의 오버 로드가 있습니다. 하나는 입력 매개 변수를 허용 하지 않고 모든 사용자를 반환 하 고, 다른 하나는 페이지 인덱스와 페이지 크기에 대 한 정수 값을 사용 하 고 지정 된 사용자 하위 집합만 반환 합니다.The Membership.GetAllUsers method has two overloads: one that accepts no input parameters and returns all of the users and one that takes in integer values for the page index and page size, and returns only the specified subset of the users. 두 번째 오버 로드는 모든 사용자가 아닌 사용자 계정의 정확한 하위 집합만 반환 하기 때문에 사용자를 보다 효율적으로 페이징 하는 데 사용할 수 있습니다.The second overload can be used to more efficiently page through the users since it returns just the precise subset of user accounts rather than all of them. 사용자 계정이 수천 개인 경우 필터 기반 인터페이스를 사용 하는 것이 좋습니다. 예를 들어 사용자 이름이 선택한 문자로 시작 하는 사용자만 표시 됩니다.If you have thousands of user accounts, you might want to consider a filter-based interface, one that only shows those users whose UserName begins with a selected character, for instance. Membership.FindUsersByName method 는 필터 기반 사용자 인터페이스를 작성 하는 데 적합 합니다.The Membership.FindUsersByName method is ideal for building a filter-based user interface. 이후 자습서에서 이러한 인터페이스를 빌드하는 방법을 살펴보겠습니다.We will look at building such an interface in a future tutorial.

GridView 컨트롤은 SqlDataSource 또는 ObjectDataSource와 같이 올바르게 구성 된 데이터 소스 컨트롤에 컨트롤이 바인딩될 때 기본 제공 편집 및 삭제 지원을 제공 합니다.The GridView control offers built-in editing and deleting support when the control is bound to a properly configured data source control, such as the SqlDataSource or ObjectDataSource. 그러나 UserGrid GridView는 해당 데이터를 프로그래밍 방식으로 바인딩합니다. 따라서 이러한 두 가지 작업을 수행 하는 코드를 작성 해야 합니다.The UserGrid GridView, however, has its data programmatically bound; therefore, we must write code to perform these two tasks. 특히, 방문자가 GridView의 편집, 취소, 업데이트 또는 삭제 단추를 클릭할 때 발생 하는 GridView의 RowEditing, RowCancelingEdit, RowUpdatingRowDeleting 이벤트에 대 한 이벤트 처리기를 만들어야 합니다.In particular, we will need to create event handlers for the GridView's RowEditing, RowCancelingEdit, RowUpdating, and RowDeleting events, which are fired when a visitor clicks the GridView's Edit, Cancel, Update, or Delete buttons.

먼저 GridView의 RowEditing, RowCancelingEditRowUpdating 이벤트에 대 한 이벤트 처리기를 만든 후 다음 코드를 추가 합니다.Start by creating the event handlers for the GridView's RowEditing, RowCancelingEdit, and RowUpdating events and then add the following code:

protected void UserGrid_RowEditing(object sender, GridViewEditEventArgs e)
{
     // Set the grid's EditIndex and rebind the data

     UserGrid.EditIndex = e.NewEditIndex;
     BindUserGrid();
}

protected void UserGrid_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
{
     // Revert the grid's EditIndex to -1 and rebind the data
     UserGrid.EditIndex = -1;
     BindUserGrid();
}

protected void UserGrid_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
     // Exit if the page is not valid
     if (!Page.IsValid)
          return;

     // Determine the username of the user we are editing
     string UserName = UserGrid.DataKeys[e.RowIndex].Value.ToString();

     // Read in the entered information and update the user
     TextBox EmailTextBox = UserGrid.Rows[e.RowIndex].FindControl("Email") as TextBox;
     TextBox CommentTextBox = UserGrid.Rows[e.RowIndex].FindControl("Comment") as TextBox;

     // Return information about the user
     MembershipUser UserInfo = Membership.GetUser(UserName);

     // Update the User account information
     UserInfo.Email = EmailTextBox.Text.Trim();
     UserInfo.Comment = CommentTextBox.Text.Trim();

     Membership.UpdateUser(UserInfo);

     // Revert the grid's EditIndex to -1 and rebind the data
     UserGrid.EditIndex = -1;
     BindUserGrid();
}

RowEditingRowCancelingEdit 이벤트 처리기는 GridView의 EditIndex 속성을 설정한 다음 사용자 계정 목록을 표에 다시 바인딩합니다.The RowEditing and RowCancelingEdit event handlers simply set the GridView's EditIndex property and then rebind the list of user accounts to the grid. RowUpdating 이벤트 처리기에서 흥미로운 항목이 발생 합니다.The interesting stuff happens in the RowUpdating event handler. 이 이벤트 처리기는 먼저 데이터가 유효한 지 확인 한 다음 편집 된 사용자 계정의 UserName 값을 DataKeys 컬렉션에서 가져와 합니다.This event handler starts by ensuring that the data is valid and then grabs the UserName value of the edited user account from the DataKeys collection. 그런 다음 두 개의 템플릿 필드 (EditItemTemplate)의 EmailComment 텍스트 상자를 프로그래밍 방식으로 참조 합니다.The Email and Comment TextBoxes in the two TemplateFields' EditItemTemplate s are then programmatically referenced. 해당 Text 속성은 편집 된 전자 메일 주소와 주석을 포함 합니다.Their Text properties contain the edited email address and comment.

멤버 자격 API를 통해 사용자 계정을 업데이트 하려면 먼저 Membership.GetUser(userName)에 대 한 호출을 통해 사용자 정보를 가져와야 합니다.In order to update a user account through the Membership API we need to first get the user's information, which we do via a call to Membership.GetUser(userName). 그러면 반환 된 MembershipUser 개체의 EmailComment 속성이 편집 인터페이스에서 두 텍스트 상자에 입력 된 값으로 업데이트 됩니다.The returned MembershipUser object's Email and Comment properties are then updated with the values entered into the two TextBoxes from the editing interface. 마지막으로 이러한 수정 내용은 Membership.UpdateUser에 대 한 호출과 함께 저장 됩니다.Finally, these modifications are saved with a call to Membership.UpdateUser. RowUpdating 이벤트 처리기는 GridView를 사전 편집 인터페이스로 되돌리면 완료 됩니다.The RowUpdating event handler completes by reverting the GridView to its pre-editing interface.

그런 다음 RowDeleting 이벤트 처리기를 만들고 다음 코드를 추가 합니다.Next, create the RowDeleting event handler and then add the following code:

protected void UserGrid_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
     // Determine the username of the user we are editing
     string UserName = UserGrid.DataKeys[e.RowIndex].Value.ToString();

     // Delete the user
     Membership.DeleteUser(UserName);

     // Revert the grid's EditIndex to -1 and rebind the data
     UserGrid.EditIndex = -1;
     BindUserGrid();
}

위의 이벤트 처리기는 먼저 GridView의 DataKeys collection에서 UserName 값을 수집 합니다. 그런 다음이 UserName 값은 멤버 자격 클래스의 DeleteUser 메서드에전달 됩니다.The above event handler starts by grabbing the UserName value from the GridView's DataKeys collection; this UserName value is then passed into the Membership class's DeleteUser method. DeleteUser 메서드는 관련 된 멤버 자격 데이터 (예:이 사용자가 속한 역할)를 포함 하 여 시스템에서 사용자 계정을 삭제 합니다.The DeleteUser method deletes the user account from the system, including related membership data (such as what roles this user belongs to). EditIndex 사용자를 삭제 한 후에는 사용자가 삭제를 클릭 하 여 다른 행이 편집 모드에 있는 동안에는 사용자가 삭제를 클릭 한 경우에는-1로 설정 되 고 BindUserGrid 메서드가 호출 됩니다.After deleting the user, the grid's EditIndex is set to -1 (in case the user clicked Delete while another row was in edit mode) and the BindUserGrid method is called.

Note

사용자 계정을 삭제 하기 전에는 삭제 단추에 사용자의 확인이 필요 하지 않습니다.The Delete button does not require any sort of confirmation from the user before deleting the user account. 계정이 실수로 삭제 될 가능성을 줄이기 위해 일종의 사용자 확인을 추가 하는 것이 좋습니다.I encourage you to add some form of user confirmation to lessen the chance of an account being accidentally deleted. 동작을 확인 하는 가장 쉬운 방법 중 하나는 클라이언트 쪽 확인 대화 상자를 통하는 것입니다.One of the easiest ways to confirm an action is through a client-side confirm dialog box. 이 기술에 대 한 자세한 내용은 삭제할 때 클라이언트 쪽 확인 추가를 참조 하세요.For more information on this technique, see Adding Client-Side Confirmation When Deleting.

이 페이지가 예상 대로 작동 하는지 확인 합니다.Verify that this page functions as expected. 사용자의 전자 메일 주소와 의견을 편집 하 고 모든 사용자 계정을 삭제할 수 있어야 합니다.You should be able to edit any user's email address and comment, as well as delete any user account. RoleBasedAuthorization.aspx 페이지에는 모든 사용자가 액세스할 수 있으므로 익명 방문자 라도이 페이지를 방문 하 여 사용자 계정을 편집 하 고 삭제할 수 있습니다.Since the RoleBasedAuthorization.aspx page is accessible to all users, any user – even anonymous visitors – can visit this page and edit and delete user accounts! 감독자 및 관리자 역할의 사용자만 사용자의 이메일 주소와 의견을 편집할 수 있으며 관리자만 사용자 계정을 삭제할 수 있도록이 페이지를 업데이트 해 보겠습니다.Let's update this page so that only users in the Supervisors and Administrators roles can edit a user's email address and comment, and only Administrators can delete a user account.

"LoginView 컨트롤 사용" 섹션에서는 LoginView 컨트롤을 사용 하 여 사용자의 역할과 관련 된 지침을 표시 하는 방법을 보여 줍니다.The "Using the LoginView Control" section looks at using the LoginView control to show instructions specific to the user's role. 관리자 역할의 사용자가이 페이지를 방문 하는 경우 사용자를 편집 하 고 삭제 하는 방법에 대 한 지침이 표시 됩니다.If a person in the Administrators role visits this page, we will show instructions on how to edit and delete users. 감독자 역할의 사용자가이 페이지에 도달 하면 사용자 편집에 대 한 지침이 표시 됩니다.If a user in the Supervisors role reaches this page, we will show instructions on editing users. 그리고 방문자가 익명 이거나 감독자 또는 관리자 역할에 속하지 않는 경우 사용자 계정 정보를 편집 하거나 삭제할 수 없다는 메시지가 표시 됩니다.And if the visitor is anonymous or is not in either the Supervisors or Administrators role, we will display a message explaining that they cannot edit or delete user account information. "프로그래밍 방식 제한 기능" 섹션에서 사용자의 역할에 따라 편집 및 삭제 단추를 프로그래밍 방식으로 표시 하거나 숨기는 코드를 작성 합니다.In the "Programmatically Limiting Functionality" section we will write code that programmatically shows or hides the Edit and Delete buttons based on the user's role.

LoginView 컨트롤 사용Using the LoginView Control

이전 자습서에서 살펴본 것 처럼 LoginView 컨트롤은 인증 된 사용자와 익명 사용자에 대해 서로 다른 인터페이스를 표시 하는 데 유용 하지만 LoginView 컨트롤을 사용 하 여 사용자의 역할에 따라 다른 태그를 표시할 수도 있습니다.As we've seen in past tutorials, the LoginView control is useful for displaying different interfaces for authenticated and anonymous users, but the LoginView control can also be used to display different markup based on the user's roles. LoginView 컨트롤을 사용 하 여 방문한 사용자의 역할에 따라 다른 지침을 표시 해 보겠습니다.Let's use a LoginView control to display different instructions based on the visiting user's role.

UserGrid GridView 위에 LoginView를 추가 하 여 시작 합니다.Start by adding a LoginView above the UserGrid GridView. 앞에서 설명한 대로 LoginView 컨트롤에는 두 개의 기본 제공 템플릿 인 AnonymousTemplateLoggedInTemplate있습니다.As we've discussed earlier, the LoginView control has two built-in templates: AnonymousTemplate and LoggedInTemplate. 사용자 정보를 편집 하거나 삭제할 수 없음을 사용자에 게 알리는 두 템플릿 모두에 간단한 메시지를 입력 합니다.Enter a brief message in both of these templates that informs the user that they cannot edit or delete any user information.

<asp:LoginView ID="LoginView1" runat="server">
     <LoggedInTemplate>
          You are not a member of the Supervisors or Administrators roles. Therefore you
          cannot edit or delete any user information.
     </LoggedInTemplate>
     <AnonymousTemplate>
          You are not logged into the system. Therefore you cannot edit or delete any user

          information.
     </AnonymousTemplate>
</asp:LoginView>

AnonymousTemplateLoggedInTemplate외에도 LoginView 컨트롤에는 역할 관련 템플릿인 Rolegroups가 포함 될 수 있습니다.In addition to the AnonymousTemplate and LoggedInTemplate, the LoginView control can include RoleGroups, which are role-specific templates. 각 RoleGroup에는 단일 속성인 Roles이 포함 되어 있습니다 .이 속성은 RoleGroup이 적용 되는 역할을 지정 합니다.Each RoleGroup contains a single property, Roles, which specifies what roles the RoleGroup applies to. Roles 속성은 단일 역할 (예: "Administrators") 또는 쉼표로 구분 된 역할 목록 (예: "Administrators, 감독자")으로 설정할 수 있습니다.The Roles property can be set to a single role (like "Administrators") or to a comma-delimited list of roles (like "Administrators, Supervisors").

RoleGroups를 관리 하려면 컨트롤의 스마트 태그에서 "RoleGroups 편집" 링크를 클릭 하 여 Rolegroups 컬렉션 편집기를 엽니다.To manage the RoleGroups, click the "Edit RoleGroups" link from the control's Smart Tag to bring up the RoleGroup Collection Editor. 두 개의 새 RoleGroups를 추가 합니다.Add two new RoleGroups. 첫 번째 RoleGroup의 Roles 속성을 "Administrators"로, 두 번째는 "감독자"로 설정 합니다.Set the first RoleGroup's Roles property to "Administrators" and the second's to "Supervisors".

RoleGroup 컬렉션 편집기를 통해 LoginView의 역할별 템플릿을 관리 하는 Manage the LoginView's Role-Specific Templates Through the RoleGroup Collection Editor

그림 8: Rolegroup 컬렉션 편집기를 통해 LoginView의 역할별 템플릿 관리 (전체 크기 이미지를 보려면 클릭)Figure 8: Manage the LoginView's Role-Specific Templates Through the RoleGroup Collection Editor (Click to view full-size image)

확인을 클릭 하 여 RoleGroup 컬렉션 편집기를 닫습니다. 이렇게 하면 LoginView의 선언적 태그가 업데이트 되어 RoleGroup 컬렉션 편집기에 정의 된 각 RoleGroup에 대 한 <asp:RoleGroup> 자식 요소가 포함 된 <RoleGroups> 섹션이 포함 됩니다.Click OK to close the RoleGroup Collection Editor; this updates the LoginView's declarative markup to include a <RoleGroups> section with an <asp:RoleGroup> child element for each RoleGroup defined in the RoleGroup Collection Editor. 또한 LoginView의 스마트 태그에 있는 "Views" 드롭다운 목록에는 처음에 AnonymousTemplateLoggedInTemplate만 나열 됩니다. 이제 추가 된 RoleGroups도 포함 됩니다.Furthermore, the "Views" drop-down list in the LoginView's Smart Tag - which initially listed just the AnonymousTemplate and LoggedInTemplate – now includes the added RoleGroups as well.

감독자 역할의 사용자에 게는 사용자 계정을 편집 하는 방법에 대 한 지침이 표시 되 고 관리자 역할의 사용자에 게는 편집 및 삭제 지침이 표시 되도록 RoleGroups를 편집 합니다.Edit the RoleGroups so that users in the Supervisors role are displayed instructions on how to edit user accounts, while users in the Administrators role are shown instructions for editing and deleting. 이러한 변경을 수행한 후에는 LoginView의 선언적 태그가 다음과 같이 표시 됩니다.After making these changes, your LoginView's declarative markup should look similar to the following.

<asp:LoginView ID="LoginView1" runat="server">
     <RoleGroups>
          <asp:RoleGroup Roles="Administrators">
               <ContentTemplate>
                    As an Administrator, you may edit and delete user accounts. 
                    Remember: With great power comes great responsibility!

               </ContentTemplate>
          </asp:RoleGroup>
          <asp:RoleGroup Roles="Supervisors">
               <ContentTemplate>
                    As a Supervisor, you may edit users&#39; Email and Comment information. 
                    Simply click the Edit button, make your changes, and then click Update.
               </ContentTemplate>
          </asp:RoleGroup>
     </RoleGroups>

     <LoggedInTemplate>
          You are not a member of the Supervisors or Administrators roles. 
          Therefore you cannot edit or delete any user information.
     </LoggedInTemplate>
     <AnonymousTemplate>
          You are not logged into the system. Therefore you cannot edit or delete any user
          information.
     </AnonymousTemplate>
</asp:LoginView>

이러한 변경을 수행한 후에는 페이지를 저장 하 고 브라우저를 통해 방문 합니다.After making these changes, save the page and then visit it through a browser. 먼저 익명 사용자로 페이지를 방문 합니다.First visit the page as an anonymous user. "시스템에 로그인 하지 않았습니다." 라는 메시지가 표시 됩니다.You should be shown the message, "You are not logged into the system. 따라서 사용자 정보를 편집 하거나 삭제할 수 없습니다. "Therefore you cannot edit or delete any user information." 그런 다음 인증 된 사용자로 로그인 하지만 감독자 또는 관리자 역할에는 없습니다.Then log in as an authenticated user, but one that is neither in the Supervisors nor Administrators role. 이번에는 "사용자가 감독자 또는 관리자 역할의 구성원이 아닙니다." 라는 메시지가 표시 됩니다.This time you should see the message, "You are not a member of the Supervisors or Administrators roles. 따라서 사용자 정보를 편집 하거나 삭제할 수 없습니다. "Therefore you cannot edit or delete any user information."

다음으로, 감독자 역할의 구성원 인 사용자로 로그인 합니다.Next, log in as a user who is a member of the Supervisors role. 이번에는 감독자 역할 관련 메시지가 표시 됩니다 (그림 9 참조).This time you should see the Supervisors role-specific message (see Figure 9). 그리고 관리자 역할의 사용자로 로그인 하는 경우 관리자 역할 관련 메시지가 표시 됩니다 (그림 10 참조).And if you log in as a user in the Administrators role you should see the Administrators role-specific message (see Figure 10).

Bruce는 감독자 역할 관련 메시지를 표시 합니다.Bruce is Shown the Supervisors Role-Specific Message

그림 9: 감독자 역할 특정 메시지 표시 (전체 크기 이미지를 보려면 클릭)Figure 9: Bruce is Shown the Supervisors Role-Specific Message (Click to view full-size image)

Tito는 관리자 역할 관련 메시지를 표시 합니다.Tito is Shown the Administrators Role-Specific Message

그림 10: 관리자 역할 관련 메시지 (전체 크기 이미지를 보려면 클릭)가 표시 됩니다.Figure 10: Tito is Shown the Administrators Role-Specific Message (Click to view full-size image)

그림 9 및 10의 스크린 샷 처럼 LoginView는 여러 템플릿이 적용 되는 경우에도 하나의 템플릿만 렌더링 합니다.As the screen shots in Figures 9 and 10 show, the LoginView only renders one template, even if multiple templates apply. Bruce와 Tito가 모두 로그인 되어 있지만 LoginView은 일치 하는 RoleGroup만 렌더링 하 고 LoggedInTemplate는 렌더링 하지 않습니다.Bruce and Tito are both logged in users, yet the LoginView renders only the matching RoleGroup and not the LoggedInTemplate. 또한 Tito는 관리자와 감독자 역할 모두에 속하지만 LoginView 컨트롤은 감독자 1 대신 관리자 역할 관련 템플릿을 렌더링 합니다.Moreover, Tito belongs to both the Administrators and Supervisors roles, yet the LoginView control renders the Administrators role-specific template instead of the Supervisors one.

그림 11에서는 LoginView 컨트롤에서 렌더링할 템플릿을 결정 하는 데 사용 하는 워크플로를 보여 줍니다.Figure 11 illustrates the workflow used by the LoginView control to determine what template to render. 하나 이상의 RoleGroup이 지정 된 경우 LoginView 템플릿은 일치 하는 첫 번째 rolegroup을 렌더링 합니다.Note that if there is more than one RoleGroup specified, the LoginView template renders the first RoleGroup that matches. 즉, 감독자 RoleGroup을 첫 번째 RoleGroup으로 배치 하 고 관리자를 두 번째로 배치 했다면 Tito이 페이지를 방문 하면 감독자 메시지가 표시 됩니다.In other words, if we had placed the Supervisors RoleGroup as the first RoleGroup and the Administrators as the second, then when Tito visited this page he would see the Supervisors message.

LoginView 컨트롤의 워크플로를 하 여 렌더링할 템플릿 결정The LoginView Control's Workflow for Determining What Template to Render

그림 11: 렌더링할 템플릿을 결정 하는 LoginView 컨트롤의 워크플로 (전체 크기 이미지를 보려면 클릭)Figure 11: The LoginView Control's Workflow for Determining What Template to Render (Click to view full-size image)

프로그래밍 방식으로 기능 제한Programmatically Limiting Functionality

LoginView 컨트롤은 페이지를 방문 하는 사용자의 역할에 따라 다른 명령을 표시 하지만 편집 및 취소 단추는 모두에 게 표시 됩니다.While the LoginView control displays different instructions based on the role of the user visiting the page, the Edit and Cancel buttons remain visible to all. 감독자 또는 관리자 역할이 아닌 익명 방문자와 사용자에 대 한 편집 및 삭제 단추를 프로그래밍 방식으로 숨기는 것이 필요 합니다.We need to programmatically hide the Edit and Delete buttons for anonymous visitors and users who are in neither the Supervisors nor Administrators role. 관리자가 아닌 모든 사용자에 대 한 삭제 단추를 숨겨야 합니다.We need to hide the Delete button for everyone who is not an Administrator. 이를 수행 하기 위해 필요한 경우 CommandField의 Edit 및 Delete Linkbutton를 프로그래밍 방식으로 참조 하는 코드를 작성 하 고 Visible 속성을 false로 설정 합니다.In order to accomplish this we will write a bit of code that programmatically references the CommandField's Edit and Delete LinkButtons and sets their Visible properties to false, if necessary.

CommandField에서 프로그래밍 방식으로 컨트롤을 참조 하는 가장 쉬운 방법은 먼저 템플릿으로 변환 하는 것입니다.The easiest way to programmatically reference controls in a CommandField is to first convert it to a template. 이를 수행 하려면 GridView의 스마트 태그에서 "열 편집" 링크를 클릭 하 고 현재 필드 목록에서 CommandField를 선택한 다음 "이 필드를 Templatefield로 변환으로 변환" 링크를 클릭 합니다.To accomplish this, click the "Edit Columns" link from the GridView's Smart Tag, select the CommandField from the list of current fields, and click the "Convert this field into a TemplateField" link. 이렇게 하면 CommandField가 ItemTemplateEditItemTemplate있는 Templatefield로 변환으로 전환 됩니다.This turns the CommandField into a TemplateField with an ItemTemplate and EditItemTemplate. ItemTemplate에는 EditItemTemplate 업데이트 및 취소 Linkbutton 있는 동안 편집 및 삭제 Linkbutton 포함 됩니다.The ItemTemplate contains the Edit and Delete LinkButtons while the EditItemTemplate houses the Update and Cancel LinkButtons.

CommandField를 Templatefield로 변환으로 변환 Convert the CommandField Into a TemplateField

그림 12: Commandfield를 templatefield로 변환으로 변환 (전체 크기 이미지를 보려면 클릭)Figure 12: Convert the CommandField Into a TemplateField (Click to view full-size image)

ID 속성을 EditButtonDeleteButton값으로 설정 하 여 ItemTemplate편집 및 삭제 Linkbutton를 업데이트 합니다.Update the Edit and Delete LinkButtons in the ItemTemplate, setting their ID properties to values of EditButton and DeleteButton, respectively.

<asp:TemplateField ShowHeader="False">
     <EditItemTemplate>
          <asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="True"
               CommandName="Update" Text="Update"></asp:LinkButton>

           <asp:LinkButton ID="LinkButton2" runat="server" CausesValidation="False"
                CommandName="Cancel" Text="Cancel"></asp:LinkButton>

     </EditItemTemplate>
     <ItemTemplate>
          <asp:LinkButton ID="EditButton" runat="server" CausesValidation="False"
               CommandName="Edit" Text="Edit"></asp:LinkButton>

           <asp:LinkButton ID="DeleteButton" runat="server" CausesValidation="False"
               CommandName="Delete" Text="Delete"></asp:LinkButton>

     </ItemTemplate>
</asp:TemplateField>

데이터가 GridView에 바인딩될 때마다 GridView는 DataSource 속성의 레코드를 열거 하 고 해당 GridViewRow 개체를 생성 합니다.Whenever data is bound to the GridView, the GridView enumerates the records in its DataSource property and generates a corresponding GridViewRow object. GridViewRow 개체가 만들어질 때마다 RowCreated 이벤트가 발생 합니다.As each GridViewRow object is created, the RowCreated event is fired. 권한 없는 사용자에 대 한 편집 및 삭제 단추를 숨기려면이 이벤트에 대 한 이벤트 처리기를 만들고 Linkbutton 편집 및 삭제를 프로그래밍 방식으로 참조 하 여 Visible 속성을 적절 하 게 설정 해야 합니다.In order to hide the Edit and Delete buttons for unauthorized users, we need to create an event handler for this event and programmatically reference the Edit and Delete LinkButtons, setting their Visible properties accordingly.

이벤트 처리기 RowCreated 이벤트를 만들고 다음 코드를 추가 합니다.Create an event handler the RowCreated event and then add the following code:

protected void UserGrid_RowCreated(object sender, GridViewRowEventArgs e)
{
     if (e.Row.RowType == DataControlRowType.DataRow && e.Row.RowIndex != UserGrid.EditIndex)
     {
          // Programmatically reference the Edit and Delete LinkButtons
          LinkButton EditButton = e.Row.FindControl("EditButton") as LinkButton;

          LinkButton DeleteButton = e.Row.FindControl("DeleteButton") as LinkButton;

          EditButton.Visible = (User.IsInRole("Administrators") || User.IsInRole("Supervisors"));
          DeleteButton.Visible = User.IsInRole("Administrators");
     }
}

RowCreated 이벤트는 헤더, 바닥글, 호출기 인터페이스 등을 비롯 한 모든 GridView 행에 대해 발생 합니다.Keep in mind that the RowCreated event fires for all of the GridView rows, including the header, the footer, the pager interface, and so forth. 편집 모드에 있지 않은 데이터 행을 처리 하는 경우에만 편집 및 삭제 Linkbutton를 프로그래밍 방식으로 참조 하려고 합니다. 편집 모드의 행에는 편집 및 삭제 대신 업데이트 및 취소 단추가 있기 때문입니다.We only want to programmatically reference the Edit and Delete LinkButtons if we are dealing with a data row not in edit mode (since the row in edit mode has Update and Cancel buttons instead of Edit and Delete). 이 검사는 if 문에 의해 처리 됩니다.This check is handled by the if statement.

편집 모드에 있지 않은 데이터 행을 처리 하는 경우에는 편집 및 삭제 Linkbutton이 참조 되 고 해당 Visible 속성은 User 개체의 IsInRole(roleName) 메서드에서 반환 된 부울 값을 기반으로 설정 됩니다.If we are dealing with a data row that is not in edit mode, the Edit and Delete LinkButtons are referenced and their Visible properties are set based on the Boolean values returned by the User object's IsInRole(roleName) method. 사용자 개체는 RoleManagerModule에서 만든 보안 주체를 참조 합니다. 따라서 IsInRole(roleName) 메서드는 Roles API를 사용 하 여 현재 방문자가 roleName에 속하는지 여부를 확인 합니다.The User object references the principal created by the RoleManagerModule; consequently, the IsInRole(roleName) method uses the Roles API to determine whether the current visitor belongs to roleName.

Note

역할 클래스를 직접 사용 하 여 User.IsInRole(roleName)에 대 한 호출을 Roles.IsUserInRole(roleName) 메서드에대 한 호출로 바꿀 수 있습니다.We could have used the Roles class directly, replacing the call to User.IsInRole(roleName) with a call to the Roles.IsUserInRole(roleName) method. 이 예제에서는 역할 API를 직접 사용 하는 것 보다 효율적 이기 때문에 principal 개체의 IsInRole(roleName) 메서드를 사용 하기로 결정 했습니다.I decided to use the principal object's IsInRole(roleName) method in this example because it is more efficient than using the Roles API directly. 이 자습서의 앞부분에서 사용자의 역할을 쿠키에 캐시 하도록 역할 관리자를 구성 했습니다.Earlier in this tutorial we configured the role manager to cache the user's roles in a cookie. 이 캐시 된 쿠키 데이터는 주 서버의 IsInRole(roleName) 메서드가 호출 되는 경우에만 사용 됩니다. 역할 API에 대 한 직접 호출에는 항상 역할 저장소에 대 한 마이그레이션이 포함 됩니다.This cached cookie data is only utilized when the principal's IsInRole(roleName) method is called; direct calls to the Roles API always involve a trip to the role store. 역할이 쿠키에 캐시 되지 않은 경우에도 요청 하는 동안 처음으로 호출 될 때 해당 결과를 캐시 하기 때문에 주 개체의 IsInRole(roleName) 메서드를 호출 하는 것이 더 효율적입니다.Even if roles are not cached in a cookie, calling the principal object's IsInRole(roleName) method is usually more efficient because when it is called for the first time during a request it caches the results. 반면에 역할 API는 캐싱을 수행 하지 않습니다.The Roles API, on the other hand, does not perform any caching. RowCreated 이벤트는 GridView의 모든 행에 대해 한 번만 발생 하기 때문에 User.IsInRole(roleName)를 사용 하면 역할 저장소에 대 한 한 번의 이동이 포함 되지만, Roles.IsUserInRole(roleName) n 번의 이동이 필요 합니다. 여기서 n 은 그리드에 표시 되는 사용자 계정 수입니다.Because the RowCreated event is fired once for every row in the GridView, using User.IsInRole(roleName) involves just one trip to the role store whereas Roles.IsUserInRole(roleName) requires N trips, where N is the number of user accounts displayed in the grid.

이 페이지를 방문 하는 사용자가 Administrators 또는 감독자 역할에 있는 경우 편집 단추의 Visible 속성이 true로 설정 됩니다. 그렇지 않으면 false로 설정 됩니다.The Edit button's Visible property is set to true if the user visiting this page is in the Administrators or Supervisors role; otherwise it is set to false. 사용자가 관리자 역할에 있는 경우에만 Delete 단추의 Visible 속성이 true로 설정 됩니다.The Delete button's Visible property is set to true only if the user is in the Administrators role.

브라우저를 통해이 페이지를 테스트 합니다.Test this page through a browser. 페이지를 익명 방문자로 방문 하거나 감독자 또는 관리자가 아닌 사용자로 방문 하는 경우 CommandField는 비어 있습니다. 여전히 존재 하지만 편집 또는 삭제 단추가 없는 씬 슬라이버로 사용 됩니다.If you visit the page as an anonymous visitor or as a user that is neither a Supervisor nor an Administrator, the CommandField is empty; it still exists, but as a thin sliver without the Edit or Delete buttons.

Note

비관리자 및 비관리자가 페이지를 방문 하는 경우 CommandField를 모두 숨길 수 있습니다.It is possible to hide the CommandField altogether when a non-Supervisor and non-Administrator is visiting the page. 독자를 위한 연습으로 남겨 둡니다.I leave this as an exercise for the reader.

비 감독자 및 비관리자에 대해 편집 및 삭제 단추가 숨겨진 The Edit and Delete Buttons are Hidden for Non-Supervisors and Non-Administrators

그림 13: 비 감독자 및 비관리자에 대해 편집 및 삭제 단추가 숨겨짐 (전체 크기 이미지를 보려면 클릭)Figure 13: The Edit and Delete Buttons are Hidden for Non-Supervisors and Non-Administrators (Click to view full-size image)

감독자 역할 (관리자 역할에는 아님)에 속하는 사용자가 방문 하는 경우에만 편집 단추를 볼 수 있습니다.If a user that belongs to the Supervisors role (but not to the Administrators role) visits, he sees only the Edit button.

편집 단추를 감독자에 게 사용할 수 있는 동안에는 삭제 단추가 숨겨집니다.While the Edit Button is Available for Supervisors, the Delete Button is Hidden

그림 14: 감독자에 대해 편집 단추를 사용할 수 있는 경우 삭제 단추가 숨겨집니다 (전체 크기 이미지를 보려면 클릭).Figure 14: While the Edit Button is Available for Supervisors, the Delete Button is Hidden (Click to view full-size image)

그리고 관리자가 방문 하는 경우 편집 및 삭제 단추에 대 한 액세스 권한이 있습니다.And if an Administrator visits, she has access to both the Edit and Delete buttons.

편집 및 삭제 단추 관리자만 사용할 수 있음The Edit and Delete Buttons are Available Only for Administrators

그림 15: 관리자만 편집 및 삭제 단추를 사용할 수 있음 (전체 크기 이미지를 보려면 클릭)Figure 15: The Edit and Delete Buttons are Available Only for Administrators (Click to view full-size image)

3 단계: 클래스 및 메서드에 역할 기반 권한 부여 규칙 적용Step 3: Applying Role-Based Authorization Rules to Classes and Methods

2 단계에서는 감독자 및 관리자 역할의 사용자에 대 한 편집 기능을 제한 하 고 관리자만 기능을 삭제 합니다.In Step 2 we limited edit capabilities to users in the Supervisors and Administrators roles and delete capabilities to Administrators only. 이는 프로그래밍 기법을 통해 권한이 없는 사용자에 대해 연결 된 사용자 인터페이스 요소를 숨겨서 수행 했습니다.This was accomplished by hiding the associated user interface elements for unauthorized users through programmatic techniques. 이러한 측정값은 권한 없는 사용자가 권한 있는 작업을 수행할 수 없음을 보장 하지 않습니다.Such measures do not guarantee that an unauthorized user will be unable to perform a privileged action. 나중에 추가 되거나 권한이 없는 사용자에 대해 숨기지 않는 사용자 인터페이스 요소가 있을 수 있습니다.There may be user interface elements that are added later or that we forgot to hide for unauthorized users. 또는 해커는 ASP.NET 페이지에서 원하는 메서드를 실행 하는 다른 방법을 발견할 수 있습니다.Or a hacker may discover some other way to get the ASP.NET page to execute the desired method.

권한이 없는 사용자가 특정 기능의 특정 부분에 액세스할 수 없도록 하는 쉬운 방법은 해당 클래스 또는 메서드를 PrincipalPermission 특성으로 데코레이팅 하는 것입니다.An easy way to ensure that a particular piece of functionality cannot be accessed by an unauthorized user is to decorate that class or method with the PrincipalPermission attribute. .NET 런타임이 클래스를 사용 하거나 해당 메서드 중 하나를 실행 하는 경우 현재 보안 컨텍스트에 권한이 있는지 확인 합니다.When the .NET runtime uses a class or executes one of its methods, it checks to ensure that the current security context has permission. PrincipalPermission 특성은 이러한 규칙을 정의할 수 있는 메커니즘을 제공 합니다.The PrincipalPermission attribute provides a mechanism through which we can define these rules.

사용자 기반 권한 부여 자습서에서 PrincipalPermission 특성을 다시 사용 하는 방법을 살펴보았습니다.We looked at using the PrincipalPermission attribute back in the User-Based Authorization tutorial. 구체적으로, GridView의 SelectedIndexChangedRowDeleting 이벤트 처리기를 데코레이팅하는 방법에 대해 살펴보았습니다 .이는 인증 된 사용자 및 Tito에 의해서만 실행 될 수 있도록 합니다.Specifically, we saw how to decorate the GridView's SelectedIndexChanged and RowDeleting event handler so that they could only be executed by authenticated users and Tito, respectively. PrincipalPermission 특성은 역할에 대해서만 작동 합니다.The PrincipalPermission attribute works just as well with roles.

GridView의 RowUpdatingRowDeleting 이벤트 처리기에 PrincipalPermission 특성을 사용 하 여 권한이 없는 사용자에 대 한 실행을 금지 하는 방법을 살펴보겠습니다.Let's demonstrate using the PrincipalPermission attribute on the GridView's RowUpdating and RowDeleting event handlers to prohibit execution for non-authorized users. 각 함수 정의 위에 적절 한 특성을 추가 하기만 하면 됩니다.All we need to do is add the appropriate attribute atop each function definition:

[PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
[PrincipalPermission(SecurityAction.Demand, Role = "Supervisors")]
protected void UserGrid_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
     ...
}

[PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
protected void UserGrid_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
     ...
}

RowUpdating 이벤트 처리기에 대 한 특성은 Administrators 또는 감독자 역할의 사용자만 이벤트 처리기를 실행할 수 있도록 지시 합니다. 여기서 RowDeleting 이벤트 처리기의 특성은 관리자 역할의 사용자만 실행 하도록 제한 합니다.The attribute for the RowUpdating event handler dictates that only users in the Administrators or Supervisors roles can execute the event handler, where as the attribute on the RowDeleting event handler limits the execution to users in the Administrators role.

Note

PrincipalPermission 특성은 System.Security.Permissions 네임 스페이스에서 클래스로 표현 됩니다.The PrincipalPermission attribute is represented as a class in the System.Security.Permissions namespace. 이 네임 스페이스를 가져오려면 코드 뒤 클래스 파일의 맨 위에 using System.Security.Permissions 문을 추가 해야 합니다.Be sure to add a using System.Security.Permissions statement at the top of your code-behind class file to import this namespace.

관리자가 아닌 관리자가 RowDeleting 이벤트 처리기를 실행 하려고 하거나 비관리자 또는 비관리자가 RowUpdating 이벤트 처리기를 실행 하려고 하는 경우 .NET 런타임에서 SecurityException을 발생 시킵니다.If, somehow, a non-Administrator attempts to execute the RowDeleting event handler or if a non-Supervisor or non-Administrator attempts to execute the RowUpdating event handler, the .NET runtime will raise a SecurityException.

보안 컨텍스트가 메서드를 실행할 수 있는 권한이 없으면 SecurityException이 Throw 됩니다.If the Security Context is not Authorized to Execute the Method, a SecurityException is Thrown

그림 16: 보안 컨텍스트에 메서드를 실행할 수 있는 권한이 없는 경우 SecurityException이 throw 됩니다 (전체 크기 이미지를 보려면 클릭).Figure 16: If the Security Context is not Authorized to Execute the Method, a SecurityException is Thrown (Click to view full-size image)

ASP.NET 페이지 외에도 많은 응용 프로그램에는 비즈니스 논리 및 데이터 액세스 계층과 같은 다양 한 계층을 포함 하는 아키텍처가 있습니다.In addition to ASP.NET pages, many applications also have an architecture that includes various layers, such as Business Logic and Data Access Layers. 이러한 계층은 일반적으로 클래스 라이브러리로 구현 되며 비즈니스 논리 및 데이터 관련 기능을 수행 하기 위한 구현 클래스와 메서드를 제공 합니다.These layers are typically implemented as Class Libraries and offer classes and methods for performing business logic- and data-related functionality. PrincipalPermission 특성은 이러한 계층에 권한 부여 규칙을 적용 하는 데에도 유용 합니다.The PrincipalPermission attribute is useful for applying authorization rules to these layers as well.

PrincipalPermission 특성을 사용 하 여 클래스 및 메서드에 대 한 권한 부여 규칙을 정의 하는 방법에 대 한 자세한 내용은 Scott Guthrie의 블로그 항목 PrincipalPermissionAttributes를 사용 하 여 비즈니스 및 데이터 계층에 권한 부여 규칙 추가 를 참조 하세요.For more information on using the PrincipalPermission attribute to define authorization rules on classes and methods, refer to Scott Guthrie's blog entry Adding Authorization Rules to Business and Data Layers Using PrincipalPermissionAttributes.

요약Summary

이 자습서에서는 사용자의 역할에 따라 거칠게 및 미세 수준 권한 부여 규칙을 지정 하는 방법을 살펴보았습니다.In this tutorial we looked at how to specify coarse and fine grain authorization rules based on the user's roles. ASP. NET의 URL 권한 부여 기능을 사용 하면 페이지 개발자가 페이지에 대 한 액세스가 허용 되거나 거부 되는 id를 지정할 수 있습니다.ASP.NET's URL authorization feature allows a page developer to specify what identities are allowed or denied access to what pages. 사용자 기반 권한 부여 자습서에서 살펴본 것 처럼 URL 권한 부여 규칙은 사용자를 기준으로 적용할 수 있습니다.As we saw back in the User-Based Authorization tutorial, URL authorization rules can be applied on a user-by-user basis. 또한이 자습서의 1 단계에서 살펴본 것 처럼 역할 별로 적용할 수 있습니다.They can also be applied on a role-by-role basis, as we saw in Step 1 of this tutorial.

미세 수준 권한 부여 규칙은 선언적으로 또는 프로그래밍 방식으로 적용할 수 있습니다.Fine grain authorization rules may be applied declaratively or programmatically. 2 단계에서는 LoginView 컨트롤의 RoleGroups 기능을 사용 하 여 방문한 사용자의 역할에 따라 다른 출력을 렌더링 하는 방법을 살펴보았습니다.In Step 2 we looked at using the LoginView control's RoleGroups feature to render different output based on the visiting user's roles. 또한 사용자가 특정 역할에 속하는지 여부를 프로그래밍 방식으로 확인 하는 방법과 페이지의 기능을 적절 하 게 조정 하는 방법도 살펴보았습니다.We also looked at ways to programmatically determine if a user belongs to a specific role and how to adjust the page's functionality accordingly.

행복 한 프로그래밍Happy Programming!

추가 참고 자료Further Reading

이 자습서에서 설명 하는 항목에 대 한 자세한 내용은 다음 리소스를 참조 하세요.For more information on the topics discussed in this tutorial, refer to the following resources:

저자 정보About the Author

Scott Mitchell는 여러 ASP/ASP. NET books의 작성자와 4GuysFromRolla.com의 창립자가 1998부터 Microsoft 웹 기술을 사용 하 여 작업 했습니다.Scott Mitchell, author of multiple ASP/ASP.NET books and founder of 4GuysFromRolla.com, has been working with Microsoft Web technologies since 1998. Scott은 독립 컨설턴트, 강사 및 기록기로 작동 합니다.Scott works as an independent consultant, trainer, and writer. 최신 책은 24 시간 이내에 ASP.NET 2.0을 sams teach yourself 것입니다.His latest book is Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Scott은 mitchell@4guysfromrolla.com 또는 http://ScottOnWriting.NET의 블로그를 통해 연결할 수 있습니다.Scott can be reached at mitchell@4guysfromrolla.com or via his blog at http://ScottOnWriting.NET.

특별 해 주셔서 감사 합니다.Special Thanks To…

이 자습서 시리즈는 많은 유용한 검토자가 검토 했습니다.This tutorial series was reviewed by many helpful reviewers. 이 자습서에 대 한 잠재 고객 검토자는 Suchi Banerjee 및 Teresa Murphy를 포함 합니다.Lead reviewers for this tutorial include Suchi Banerjee and Teresa Murphy. 예정 된 MSDN 문서를 검토 하는 데 관심이 있나요?Interested in reviewing my upcoming MSDN articles? 그렇다면 mitchell@4GuysFromRolla.com 에 줄을 놓습니다.If so, drop me a line at mitchell@4GuysFromRolla.com