After authenticating a principal, the next step is to determine whether that principal has permission to access the resources it is requesting. This process is known as authorization. ASP.NET works in conjunction with its primary host environment, Internet Information Services (IIS), to provide authentication and authorization services to applications.
There are several schemes to determine if an authenticated principal has authorization to access a particular resource. The security of an ASP.NET application is built upon the security infrastructure of IIS and Windows. Any communication between client and application must first pass through IIS and any process that runs on a Windows server does so in the context of an authenticated user account. When using the NTFS file system, Windows maintains an access control list (ACL) for every resource it controls, which serves as the ultimate authority for resource access permissions.
Additionally, ASP.NET applications can use configuration files to derive authorization information. All ASP.NET applications on a particular machine inherit their security configuration from a file named machine.config. Each ASP.NET application can in turn override some of the settings in machine.config using an application-level configuration file named Web.config. It is important to remember that the permissions contained in a resource's ACL override any permission granted by the configuration files. It is also important to note that ASP.NET is an ISAPI extension; it only controls access to those resources that map to Aspnet_isapi.dll. For more information, see Configuration Files.
The following items control authorization in an ASP.NET application:
- Windows Access Control Lists (ACLs)
- Web Server Permissions
- URL Authorization
- .NET Principal Objects
- Roles and Method-Level Security
Windows Access Control Lists
Using Windows ACLs, you can create file system permissions on specific application files. This solution works best if your application is authenticating users to Windows accounts. To use Windows ACLs, you must use the Windows NTFS file system. For more information, see Access-Control Lists (ACLs).
Web Server Permissions
You can configure IIS to specify the following permissions on Web site directories, such as read access and directory browsing. It is important to understand the distinction between Web server permissions and NTFS permissions. Unlike NTFS, Web server permissions apply to all users accessing your Web and FTP sites. NTFS permissions apply only to a specific user or group of users with a valid Windows account. NTFS controls access to physical directories on your server, whereas Web and FTP permissions control access to virtual directories on your Web or FTP site. For more information, see Setting Web Server Permissions in the IIS Documentation (http://www.microsoft.com/windows2000/en/server/iis/htm/core/iiwspsc.htm).
The UrlAuthorizationModule Class maps users and roles to elements within the URI namespace, which is defined by a URL. This module implements both positive and negative authorization assertions. The module can either be used to selectively permit or deny specific users access to arbitrary elements of the URI namespace. For example, you can base access on user role membership. For more information, see ASP.NET Authorization and UrlAuthorizationModule Class
The following example grants access to several domain users, while denying it to everyone else.
<!-- Web.config file --> <configuration> <system.web> <authentication mode="Windows" /> <authorization> <allow users="domain1\user, domain2\user2, domain1\user3" /> <deny users="*" /> </authorization> </system.web> </configuration>
The System.Security.Principal Namespace provides a WindowsPrincipal Class to represent the security context under which the code is running. This object is automatically created for you when you use Windows authentication in IIS. It allows you to check the Windows group membership of a Windows user account and restrict access accordingly. For more information, see Creating WindowsIdentity and WindowsPrincipal Objects
You can create an object from the GenericPrincipal Class based on your own custom roles. Use this when you have your own user/role database. You can populate the principal object in the OnAuthenticate event. You can have a custom table mapped to Windows accounts that you access in this event. Using that information, you can create a custom principal object for the authenticated user. For returning authenticated users, you can use a cookie to recreate the principal object. For more information, see Creating GenericPrincipal and GenericIdentity Objects.
Roles and Method-Level Security
You may need to use method-level security to restrict which methods a particular client principal calls. There are several approaches to this type of security.
- If you are using Windows accounts, create roles for your users by creating Windows groups. Because the processing thread is impersonating the client and a WindowsPrincipal object is available, use the following approaches:
- Create NTFS ACLs on protected resources accessed by the ASP.NET thread.
- Call the WindowsPrincipal.IsInRole method from each method to verify the caller has the appropriate permissions. You can also implement a logic statement in code that calls a particular subroutine based on the client's group membership. For more information, see WindowsPrincipal.IsInRole Method.
- If you are using a GenericPrincipal object created from users and roles contained in a custom database:
- You can programmatically check role membership by calling the GenericPrincipal.IsInRole method in the same fashion as with the WindowsPrincipal object. For more information, see GenericPrincipal.IsInRole Method.
- If you are not using a principal object, you have other options:
- The role-based security model supports a permission object similar to the permission objects found in the code access security model. This object, PrincipalPermission, represents the identity and role that a particular principal class must have to run. You can use the PrincipalPermission class for both imperative and declarative security checks. For more information, see PrincipalPermission Objects.
- Accept user credentials as parameters to the method call and perform a look-up within the method.
- Verify the existence of a cookie as the first operation of the method call.
- Create a logon method that returns a custom key value. Subsequent methods accept the key value as a parameter. This is similar to using browser-supported cookies; however, you can use it in cases where the client does not support cookies.
For more information, see Role-Based Security.
By passing a user name and role to the constructor, you can require that the identity of the principal object attached to the current thread matches a particular user name and role. After you have defined identity and principal objects, you can perform security checks against them in one of the following ways:
- Using imperative security checks. Imperative security determines at run time whether the principal object attached to the current thread matches a specified PrincipalPermission object. For more information, see Performing Imperative Security Checks.
- Using declarative security checks. Declarative security uses the PrincipalPermissionAttribute to define the principal that the current thread must have to invoke a method. For more information, see Performing Declarative Security Checks.
- Directly accessing the Principal object. By accessing the Principal object directly, you can programmatically makes a security decision based on the properties of the principal object attached to the current thread. For more information, see Directly Accessing a Principal Object.
For more information, see Role-Based Security Checks.