Sie sind auf Seite 1von 56

Security Features in ASP.

NET - Authentication Introduction Security is one of the primary concerns for both developers and application architects. As there are lots of different types of website with varying security needs, the developers need to know how the security works and choose the appropriate security model for different applications. Some websites collect no information from the users and publish the information that is available widely such as search engine. Meanwhile, there are other sites that may need to collect sensitive information from their users (e.g. credit card numbers and other personal information). These websites need much stronger security implementation to avoid malicious attacks from external entities. Difference of ASP and ASP.NET Security Flow The security flow for ASP.NET page request is different from the classic ASP security flow. In ASP, IIS impersonates the authenticated user by default, and in ASP.NET, the developer has more control over configuring security at different level [2]. ASP.NET Security Fundamental Operations Security in the context of ASP.NET application involves 3 fundamental operations [1,4,5]:

Authentication: the process of validating the identity of a user to allow or deny a request [4,9,10]. This involves accepting credentials (e.g. username and password) from the users and validating it against a designated authority. After the identity is verified and validated, the user is considered to be legal and the resource request is fulfilled. Future request from the same user ideally are not subject to the authentication process until the user logs out of the web application. Authorization: the process of ensuring that users with valid identity are allowed to access specific resources. Impersonation: this process enables an application to ensure the identity of the user, and in turn make request to the other resources. Access to resources will be granted or denied based on the identity that is being impersonated. In other words, impersonation enables a server process to run using the security credentials of the client [6,9]. Thus, the ASP.NET applications are capable to execute the identity of client on whose behalf they are operating.

Since there are a lot of ASP.NET security features to cover, this paper will only focus on authentication in ASP.NET.

Authentication in ASP.NET Authentication is one of the foremost features of web application's security. In ASP.NET, authentication is done at two levels [2]. First, IIS* will perform the required authentication then send out the request to ASP.NET, as described in Figure 1. For ASP.NET application, the underlying web server is IIS. Therefore, every ASP.NET application can continue to leverage the security options provided by IIS.

Source: MSDN Library Figure 1 - Security Flow of IIS and ASP.NET

When the user requests a specific resource on the system, that request will come to IIS. IIS authenticates the user requesting the resource and then hands off the request and the security token for the authenticating user to ASP.NET worker process. ASP.NET worker process will decide whether to impersonate the authenticated user supplied by IIS or not. If impersonation is enabled in the configuration setting in Web.config file, then ASP.NET worker process impersonates the authenticated user. Otherwise, the thread will run under the ASP.NET worker process identity. After all, ASP.NET checks whether the authenticated user is authorized to access these resources. If they are allowed to, ASP.NET serves the request; otherwise it sends an "access-denied" error message back to the user. ASP.NET provides built-in support for user authentication through several authentication providers [1,4]:

Forms-based authentication: the application is secured by using a custom authentication model with cookie support. Passport authentication: the application is secured by using Microsoft Passport authentication. Passport is a single sign-on technology developed by Microsoft for use on the web. Windows authentication: the application is secured by using integrated windows authentication where access to a web application is allowed only to those users who are able to verify their windows credentials.

There are scenarios where some applications do not use the authentication at all or the developer may want to develop custom authentication code. In this case, ASP.NET can set the authentication mode to None. However, the topic is out of scope of this article since it will only cover the Forms-based, passport and windows authentications. Forms-Based Authentication Forms-based authentication is used to implement customized logic for authenticating users without having to worry about session management using cookie. It gives developer more access to specify which files on the site can be accessed and by whom, and allows identification of a login page [3,7]. This mechanism will automatically redirect the unauthenticated user to login page and ask them to provide proper credentials (e.g. username/password combination). If login is successful, ASP.NET then issues the cookie to the user and redirect them to specific resources that they originally requested. This cookie allows the user to revisit particular protected resources without having to repeatedly log in. The mechanism is shown as below:

Figure 2 - Form Authentication Flow In figure above, the user requests the restricted resources first. This request will go to IIS first and the user is authenticated by IIS. If the anonymous access is enabled in IIS or the user is successfully authenticated, it will hand off the request to ASP.NET application. ASP.NET checks to see whether a valid authentication cookie is attached to the request. If it is, it means the user credentials has been previously authenticated. ASP.NET will then perform the authorization check. If the user is authorized to access those resources, the access will be granted. Otherwise, the "access-denied" message is sent. If the request does not have any cookie attached, ASP.NET redirects the user to the login page and solicits the credentials then resubmits for authentication. The application code checks those credentials. If authenticated, ASP.NET will attach the authentication ticket in the form of cookie to the response. If failed, the user can be redirected back to the login page telling the user that the username/password is invalid. Set Up Forms-Based Authentication Generally, setting up the Forms-based authentication involves 4 steps
[2]

1. Enable anonymous access in IIS This has to be done as most of the users are considered to be non-Windows users, so they can get through IIS to get to ASP.NET. ASP.NET will always allow anonymous access to the login page though. 2. Configure <authentication> section in Web.config file Web.config file contains the information related to the level and type of authentication service that is provided for a web application. The Formsbased authentication is enabled for a web application by setting the authentication mode attribute to Forms [3,8]:

<authentication mode="Forms"> <forms name="Login" loginURL="Login.as px" protection="All" timeout="10" path="/" /> </authentication> As shown by the code above, the name attribute is the name of HTTP cookie. The attribute loginURL is set to Login.aspx, which is the web page that is used for authenticating user credentials. The requests are redirected to particular URL in loginURL if the user is not authenticated. The cookie protection is set to All. This causes the ASP.NET runtime to not only encrypt the cookie contents, but also validate the cookie contents. The valid values for protection attribute are All, None, Encryption, and Validation [9,10] . If the value is specified to None, it does not use either encryption or validation. Specifying Encryption will encrypt the cookie using triple DES or DES encryption algorithm; the data validation is not done on the cookie. The Validation specifies to validate that the cookie data has not been altered in the transit, instead of encrypting the contents of the cookie. The timeout is set to 10, which means in 10 minutes the authentication cookie will expire. The idea behind this is to reduce the chance someone stealing the form authentication cookie. By reducing this, the cookie will be regenerated more often. The path attribute refers to the path of cookie to be sent to the client. It is set to "/" which means the cookie path is the root directory. The actual authentication (i.e. prompting the user to provide credentials) is performed by Login.aspx. The following code in Login.aspx passes the

username and password that the user entered to the static System.Web.Security.FormsAuthentication method called Authenticate:

If(FormsAuthentication.Authenticate(Username. Text, Password. Text)) { FormsAuthentication.RedirectFromLoginPage (Username. Text, false); } The code above will first check the username and password passed by the user, if they are valid, it will return true then go to the next statement. Next, it creates an authentication cookie, attaches it to the outgoing response and redirects user to original requested page. The second parameter specifies whether the authentication should be session cookie (false) or a persistent cookie (true) [7]. 3. Configure <authorization> section in Web.config file Add authorization support to section of ASP.NET web application. To do so, add the <authorization> section in Web.config file:

<configuration> <system.web> <authorization> <allow users="Cynthia" /> <deny users="*" /> </authorization> </system.web> </configuration> As explained above, after the user provides the valid credentials, the user is redirected to the specific protected page. However, The authorization section in this code will deny access to all users, but exclusively allow access to Cynthia. In some cases, the following code is used to allow any authenticated user to access the protected resources [2]:

<authorization> <deny users="?" /> <allow users="*" />

</authorization> The "?" means all unauthenticated, anonymous user unauthenticated or anonymous users. One important thing to note that the code:
[5]

. It will deny all

<deny users="*" /> <allow users="Cynthia" /> is different from:

<allow users="Cynthia" /> <deny users="*" /> since ASP.NET will stop at <deny users="*" /> and abandon the rest statements appear after that [7]. Therefore in the first one, it will deny ALL users instead of giving access to Cynthia only. 4. Create Login Page This is the last step for redirecting unauthenticated users, so they can provider their credentials, usually in a form of username and password and log on to protected resources. The login page must validate the submitted credentials against a database of some custom method. Valid usernames and passwords can be stored in the Web.config file in credentials section:

<credentials passwordFormat="Clear"> <user name="Cynthia" password="cyn"> <user name="Flora" password="flo"> <user name="Fenty" password="fang"> </credentials> However, storing password in clear text is unreasonable for security. Moreover, it is unrealistic to store thousands of names and passwords in Web.config file [2,7]. To address this problem, the usernames and passwords are stored in the database. This approach makes the Web.config file no longer have the <credentials> section. There will be also some changes in

Login.aspx since the credentials will be tested to match against result query from database that stores the usernames and passwords. In Login.aspx, instead of using FormsAuthentication.Authenticate to validate user credentials, it will call a local method (i.e. CheckValidity) which makes use a SQL query to determine whether the credentials are valid. The sample code as follows:

Bool CheckValidity(String username, String password) { SqlConnection conn = new SqlConnection ("server=localhost; database=weblogin; uid=sa; pwd="); try { conn.Open(); String sqlQuery = "select count (*) from users where username =\' " + username + "\' and password=\' " + password + "\' "; SqlCommand command = new SqlCommand(sqlQuery, conn); int count = (int)command.ExecuteScalar(); return (count>0); } catch (SqlException e) { return false; } finally { conn.Close(); } } This function will check for username and password given by the user to match against the database (i.e. users table) and it will return 0 if the credentials are not valid because there is no such record in the database, otherwise it will return 1, which means the credentials are valid. Benefit of Forms-Based Authentication There are some benefits of using Forms-based authentication

[5]

Developer can configure Forms-based authentication for various parts of the website differently because the Web.config is a hierarchical XML document.

Administrator and developer can change the authentication scheme quickly and easily in the Web.config file Administration is centralized because all the authentication entries are in one place - Web.config file.

Passport Authentication As stated above, this authentication mechanism provides a centralized authentication service that offers single sign-in for access the member sites. The following scenarios support the use of Passport Authentication [2]:

The username and password database or login page is not maintained; and Willing to provide personalized content; and The site will be used in conjunction with other Passport sites; and Willing to give single sign-in capability to the users

Set Up Passport Authentication To implement this authentication mode, Passport SDK (Software Development Kit) has to be installed on the server and register with Microsoft Passport [1,2]. The following code is specified in the Web.config file where the authentication mode is set to Passport:

<authentication mode="Passport"> <passport redirectURL="internal" /> </authentication> The redirectURL attribute of Passport section is set to internal, which means the unauthenticated request will receive common error message. The value of redirectURL may contain a string other than internal, which is considered to be a URL, which the unauthenticated request will be sent to. Windows Authentication This type of authentication is possibly the easiest of all to implement. Windows authentication can be used in conjunction with almost all authentication methods provided by IIS (e.g. Basic, Digest, NTLM or Kerberos Authentication), except Anonymous Authentication [2,4]. There is no need to write any code to validate the user as IIS has already authenticated their Windows credentials. Basically, Windows authentication makes use of the authentication capabilities of IIS. IIS will complete its authentication first then ASP.NET will use the authenticated identity's token to decide whether the access is granted or denied.

This mechanism is usually implemented when the users are part of Windows domain and the authenticated users are to be impersonated so that the code is executed in the same security context of the user's Windows account [4]. When a user requests specific resources, this request will go to IIS. IIS authenticates the user and attaches the security token to it. It will then pass the authenticated request and security token to ASP.NET. If impersonation is enabled, ASP.NET impersonates the user using the security token attached and sees whether the user is authorized to access the resources in the <authorization> section in Web.config file. If the access is granted, ASP.NET will send the requested resources through IIS, or else, it sends error message to the user. Set Up Windows Authentication The only step in implementing the Windows Authentication is to set the authentication mode to Windows and deny access to anonymous user in Web.config file as shown below:

<authentication mode="Windows"> ... </authentication> <authorization> <deny users="?" /> </authorization> The impersonation is enabled only if the code is to be under same security context as that of the user account. Again, this is done in the configuration file. Conclusion Authentication in ASP.NET is one of the best features of the web application's security, which it is divided into 3 different built-in providers: Forms-based, Passport and Windows Authentication. The Forms-based and passport authentication do not require the users to be as Windows users. Meanwhile, the windows authentication is designed for users that are part of Windows domain. Forms-based authentication provides the unauthenticated users with the login page to ask them for their credentials, and it will validate those credentials against the designated authority. Once authenticated, the valid users will be granted to access the original requested resources. Future request from those users of the protected resources will automatically be redirected without having to repeatedly log in. On the other hand, if the users are not authorized to access specific resources, it will send the access-denied message back to the users. For Passport authentication, just simply install

the Passport SDK on the server and register with Microsoft Passport. This mechanism offers a single sign-in provided by Microsoft to allow access to the member sites. Whereas, the Windows authentication is the easiest to implement as it does not require writing any code for authentication. It works in conjunction with IIS authentication mechanisms such as Basic, Digest, NTLM or Kerberos. However, it does not support for IIS Anonymous authentication. ASP.NET Security [Part I] Security is one of the most important concerns in application software development. Building a robust security model is one of the most important factors that drive the success of application software. As far as security in ASP.NET is concerned, three terms come into my mind, i.e., Authentication, Authorization and Impersonation. Put simply, authentication authenticates the users credentials and authorization relates to the resources that an authenticated user has access to. This article is the first in a series of articles on ASP.NET security and discusses these concepts and their applicability. Let us start our discussion with a brief outline on the sequence of events are as far as authentication and authorization are concerned when a new request comes in. When a new request arrives at IIS, it first checks the validity of the incoming request. If the authentication mode is anonymous (default) then the request is authenticated automatically. But if the authentication mode is overridden in the web.config file settings, IIS performs the specified authentication check before the request is passed on to ASP.NET. ASP.NET then checks whether Impersonation is enabled or not. We will discuss impersonation later in this article. If impersonation is enabled, ASP.NET executes with the identity of the entity on behalf of which it is performing the task; otherwise, the application executes with the identity of the IIS local machine and the privileges of the ASP.NET user account. Finally, the ASP.NET engine performs an authorization check on the resources requested by the authenticated user and if the user is authorized, it returns the request through IIS pipeline. The following section discusses Authentication, Authorization and

Impersonation and how we can implement them in ASP.NET applications.

Authentication Authentication determines whether a user is valid or not based on the users credentials. Note that a user can be authorized to access the resources provided the user is an authenticated user. The applications web.config file contains all of the configuration settings for an ASP.NET application. An authentication provider is used to prove the identity of the users in a system. There are three ways to authenticate a user in ASP.NET:

Forms authentication Windows authentication Passport authentication

Forms Authentication This is based on cookies where the user name and the password are stored either in a text file or a database. It supports both session and persistent cookies. After a user is authenticated, the users credentials are stored in a cookie for use in that session. When the user has not logged in and requests for a page that is secured, he or she is redirected to the login page of the application. The following code snippet illustrates how this can be implemented in ASP.NET.

<configuration> <system.web> <authentication mode="Forms"/> <forms name="LoginForm" loginUrl="LoginForm.aspx" /> <authorization>

<deny users="?"/> </authorization> </system.web> </configuration> Note that the symbol "?" indicates all Non Authenticated and Anonymous users. Typically, the user enters the username and the password, clicks the login button and the form validates the values against values from that stored in a persistent store, usually a database. The following code snippet illustrates how this can be validated. String username = txtUserName.Text; String password = txtPassword.Text; bool isUserValid = false; //Code to validate the user name and password if(isUserValid) { FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, False); else // User is not valid lblMessage.Text = Invalid login; } The RedirectFromLoginPage method creates an authentication ticket and is used to redirect an authenticated user back to the originally requested URL or the default URL. The following code snippet illustrates how we can specify the users credentials in the applications web.config file. <configuration> <system.web> <authentication mode="Forms"> <forms loginUrl="LoginForm.aspx"> <credentialspasswordFormat="Clear">

<user name="JoydipK" password="JudeK" /> </credentials> </forms> </authentication> <authorization> </system.web> </configuration> However you choose the above technique of authentication you should provide a means of encrypting the configuration file for security reasons. I will discuss these and other issues in the forthcoming articles in this series of articles on ASP.NET Security. You can also use Forms Authentication to verify the users credentials using a database where the users credentials are stored. The following code example illustrates how this can be achieved. The method ValidateUserCredentials accepts a user name and the password, connects to the database where the users credentials is stored and verifies whether the supplied users credentials are correct. private bool ValidateUserCredentials(String userName, String password) { // Connect to the database where the user credentials are stored and then verify whether the user's credentials that // are passed as parameters to this method are correct. The method would return true if success, false otherwise. } The above method can be called as illustrated in the code snippet below. bool isAuthenticatedUser = false; try { isAuthenticatedUser =

ValidateUserCredentials(txtUserName.Text,txtPassword.Text); } catch(Exception ex) { //Some typical exception handling code } if (isAuthenticatedUser == true ) { //The user is authenticated, hence, redirect to the appropriate web form and/or display appropriate messages to the user } else { //Display appropriate messages to the user indicating that the user is not authenticated } Windows Authentication Windows Authentication is used to validate a user based on the users Windows Account; however, this is only applicable in intranet environments where the administrator has full control over the users in the network. The following code snippet illustrates how we can implement Windows Authentication in ASP.NET. <authentication mode="Windows"/> <authorization> <allow users ="*" /> </authorization> Note that the symbol "*" indicates all users inclusive of Authenticated and Anonymous users. Windows authentication can be of the following types

Anonymous Authentication Basic Authentication Digest Authentication Integrated Windows Authentication

In the Anonymous Authentication mode IIS allows any user to access an ASP.NET application without any authentication checking. In Basic Authentication mode users will be required to provide the Windows user name and password; however, this is very insecure. The Digest Authentication mode is identical to Basic Authentication with the exception that the password is hashed before it is sent across the network. In Integrated Windows Authentication mode, the passwords are not sent across the network; rather, the application uses some network authentication protocols for it to operate.

Passport Authentication Passport authentication is a centralized authentication service that uses Microsoft's Passport Service to authenticate the users of an application. It allows the users to create a single sign-in name and password to access any site that has implemented the Passport single sign-in (SSI) service. The following code snippet illustrates how we can implement Passport Authentication in ASP.NET. <configuration> <system.web> <authenticationmode="Passport"> <passportredirectUrl="LoginForm.aspx" /> </authentication> <authorization> <deny users="?" /> </authorization>

</system.web> </configuration> Authorization Authorization is the process of determining the accessibility to a resource for a previously authenticated user. Note that authorization can only work on authenticated users, hence ensuring that no un-authenticated user can access the application. The syntax for specifying authorization in ASP.NET is as follows. <authorization> < [ allow | deny ] [ users ] [ roles ] [ verbs ] /> </authorization> In ASP.NET, there are the following types of authorizations.

URL Authorization File Authorization Authorization based on ACLs

File Authorization is performed by the FileAuthorizationModule, and is active when the application is configured to use Windows authentication. It checks the access control list ( ACL ) of the file to determine whether a user should have access to the file. ACL permissions are verified for the Windows identity or, if impersonation is enabled, for the Windows identity of the ASP.NET process. URL authorization is performed by the URLAuthorizationModule, which maps users and roles to URLs in ASP.NET applications. This module can be used to selectively allow or deny access to arbitrary parts of an application ( typically directories ) for specific users or roles. Authorization like authentication is specified in the web.config file of the

application. The following is an example of how we can use authorization in ASP.NET using the applications configuration file. <authorization> <allow users="Joydip"/> <deny users="Jude"/> <deny users="?"/> </authorization> It is also possible to specify the location to which the authorization settings defined in that particular location is applicable. Refer to the following code snippet that illustrates this. <configuration> <location path = "Test.aspx"> <system.web> <authorization> <allow users = "?" /> </authorization> </system.web> </location> </configuration> You can also restrict or grant a GET or POST to one or more users of the ASP.NET application. The following code snippet illustrates how we can allow the user Jude to do a POST while the other users can do only a GET. <authorization> <allow verb = "GET" users = "*" /> <allow verb = "POST" users = "Jude" /> <deny verb = "POST" users = "*" /> </authorization> Impersonation

According to MSDN, "When using impersonation, ASP.NET applications can optionally execute with the identity of the client on whose behalf they are operating. The usual reason for doing this is to avoid dealing with authentication and authorization issues in the ASP.NET application code. Instead, you rely on Microsoft Internet Information Services (IIS) to authenticate the user and either pass an authenticated token to the ASP.NET application or, if unable to authenticate the user, pass an unauthenticated token. In either case, the ASP.NET application impersonates whichever token is received if impersonation is enabled. The ASP.NET application, now impersonating the client, then relies on the settings in the NTFS directories and files to allow it to gain access, or not. Be sure to format the server file space as NTFS, so that access permissions can be set. Note that Impersonation is disabled by default and can be specified in the web.config file as shown in the code snippet given below. <identity impersonate="true"/> or <identity impersonate="false"/> To impersonate a particular identity, specify the following in your applications web.config file. <identity impersonate="true" username="joydip" password="jude"/> Conclusion We have had a look at some of the most important concepts related to ASP.NET security. Stay tuned for the other articles in this series that will discuss other aspects of ASP.NET security.

Implementing Role-Based Security with ASP.NET Before we start, let's take a quick look at what roles are, and how they might be commonly used within an application. Imagine for a moment that you have been assigned the task of converting an online forum from Classic ASP to ASP.NET. One of the hurdles that you are likely to face lies in determining the identities of the users, and then granting access to certain features based on who that user is and what "role" they play within the application. As you begin to form a picture of what roles are required, you might find that you end up with four basic "classes" of user:

1. System Administrator - this class of user can perform any task add/delete posts and forums, ban users, approved messages posted to moderated forums, etc. 2. Moderator - this user can only approve messages that were posted to moderated forums. 3. Subscriber - these are users that are registered and authorized to post new messages, but are restricted from all administrative areas of the site. 4. Other/Public - these users merely have permission to browse to public pages within the site and read-only access to forum posts. If you've come straight out of developing classic ASP applications, your first instinct may be to maintain user state in the Session object, and, then do some type of database lookup for an associated UserType to establish the role of the user. (In fact a previous 4Guys article, Logins and Permissions, demonstrates how to accomplish this "role"-based authorization using Session variables in classic ASP.) Dim currentUserID, userType currentUserID = Session("UserID") userType = myDatabaseLookupFunction( currentUserID ) ' Only allow System Administrators and Moderators Select Case userType Case "1", "2" : ' User is OK Case Else : ' Redirect to unauthorized access page End Select

Typically, classic ASP applications relied heavily on this type of model, involving repeated database lookups to retrieve role based information. With ASP.NET, however, this model changes. Before examining how roles are handled in ASP.NET, let's first translate the classic ASP Session-based code from above into VB.NET code that would appear in our ASP.NET Web page: If User.IsInRole("SysAdmin") OrElse User.IsInRole("Moderator") Then ' User is OK Else ' Redirect to unauthorized access page End If Although the above code probably doesn't mean much to you yet, it will by the time we've finished. Essentially, you can see that we interrogate a User object to extract the role information. But what is this User object?, And how does it get the role information?, I hear you asking. Principals, Roles, and Identities, Oh My! If you've done any administering of Windows you will be familiar with the concept of Users and Groups. Basically, to access a secured network you must have a user account and that account would be assigned to one or many groups. In .NET these are referred to as Identities and Roles respectively, and they are contained within a Principal object. To understand how role based authorization works you need to have an understanding of how these three elements are tied together, and how you can programmatically access their values. Let's look at each element separately. Identities Identities represent users, and as such, have properties that allow you to obtain information (such as the username) about that user. The classes for working with Identities reside in the System.Security.Principal Namespace. This namespace contains two classes: GenericIdentity and WindowsIdentity through which you can determine the properties of a user; and one interface: IIdentity that you can use to create custom Identities that can extend the base Identity type to suit needs that are specific to your application. ' Getting the username of the current user Response.Write (User.Identity.Name) ROLES Roles are simply a comma-delimited String of role names that are added to the Principal to associate the current user with a role/s. ' Creating a string of roles Dim roleString() As String = {"manager", "cleaner"} Principals A Principal contains information about the identity and role/s that the current user is associated with. It is through the Principal that you are able to check

the role membership of the current user. In many ways a Principal is the glue that binds identities, roles, and the various other pieces of information that fully describe that Principal to the application. A Principal is encapsulated by classes found in the System.Security.Principal Namespace. This namespace contains two Classes: GenericPrincipal and WindowsPrincipal through which you can determine the properties of a principal; and one interface IPrincipal that you can use to define your own custom Principals. The .NET runtime uses the Principal that is attached to the current thread to gain information about the identity and roles of a user when handling requests that require authorization. To programmatically assign your own principal settings you simply create an instance of the Principal class passing in an identity object and a comma delimited string of roles for that identity. The constructor for the Principal object looks like this: Public Sub New( _ ByVal identity As IIdentity, _ ByVal roles() As String _ ) Therefore at the time of authentication you might do something like this to add an authenticated user to a principal, assign it some roles, and attach it to the current thread. Creating your own roles ' Global.asax event handler that fires upon attempting to authenticate the user Sub Application_AuthenticateRequest(ByVal sender As Object, ByVal e As EventArgs) If Request.IsAuthenticated() Then ' create an array of roles for the current user ' these would most likely be dynamically read ' from the data store for each user. Dim arrRoles() As String = {"Manager", "Cleaner"} ' Add our Principal to the current context Thread.CurrentPrincipal = New GenericPrincipal(Context.User.Identity, arrRoles) End If End Sub This only needs to be done once because the runtime automatically copies a reference to the principal object from the calling thread to the CallContext of the new thread.

If you cast your mind back to how FormsAuthentication works, you will remember that a user is authenticated and then an authentication cookie attached to the validating Response when you call one of the appropriate static methods of the FormsAuthentication provider. It is at that moment that the Application_AuthenticateRequest handler is called. When authenticating users you do not have to do anything in this handler, nor do you need to explicitly create a new instance of the GenericPrincipal class. However, to dynamically assign custom roles to a user (which is what we are interested in today) you do need to, and the Application_AuthenticateRequest handler is the ideal place to do this. Bringing it All Together I'll stop here briefly, before we move onto the really cool stuff, to summarize the five steps needed to allow your application to implement role based checking: 1. Validate the User - check the users credentials against a data store of credentials. 2. Create an Identity Dim objIdentity As GenericIdentity = New GenericIdentity("txtUsername") 3. Get the roles for the current user Dim strRoles() As String Dim arrRoles As New ArrayList() ' do some database call that returns a reader While reader.Read() arrRoles.Add(reader("role")) End While strRoles = arrRoles.ToArray(GetType(String), String()) 4. Add the Identity and the Roles to a Principal Dim objPrincipal As GenericPrincipal = New GenericPrincipal(objIdentity, strRoles) 5. Add the Principal to the current context of the current thread Thread.CurrentPrincipal = objPrincipal Using Roles Once you have authenticated a user and defined their identity and roles there are four ways that you can interact with the Principal to enforce permissions based on memberships within the application: 1. 2. 3. 4. Configuratively Programmatically Imperatively Declaratively

Configuratively You can configure the authorization and/or the location elements within the

Web.config configuration files to grant or deny access to entire areas within the application outright, as opposed to the other 3 methods which suit a more piecemeal approach. For example, in the application that we are developing it may be necessary to ensure that only users acting as System Administrators or Moderators are allowed access to certain administrative screens. To demonstrate this, let's presume that all of the forms that allow users to moderate forum posts reside under a directory called "ForumAdmin". Rather than programatically checking the role of a user inside every file that sits in that directory, you can simply configure the Web.config file for that folder to do the checking for you. The following snippet excludes all users except for System Administrators or Moderators from accessing files in the directory that the Web.config file resides in (as well as its subdirectories): ' Snippet from Web.config <authorization> <deny users="*" /> <allow roles="SysAdmin, Moderator" /> </authorization> By placing the abovementioned Web.config at the root of the ForumAdmin directory, the application itself will inspect the roles of the user making the Request to determine whether access is granted. That's right, no additional code is neccessary, regardless of how many .aspx files are placed under that folder. (Compare that to classic ASP and the Session-based approach, where every "sensitive" page needs to have a check at the top of the page to determine if the user has rights to view the page...) Even from this simple example, you should get an idea of how this new approach simplifies the task of authorization, and, how it supersedes the methods available under the current practices of classic ASP. Programmatically Alternatively, you may have directories that contain files that will be accessed by users acting in a wide variety of roles. An example of this would be the directory that displays the actual forum itself. You need to allow viewing access to all areas of the forum, even to unauthenticated members of the public, but to create a new post, it is imperative that a user not be in the role of Public or Other. In your code, whenever you need to check to see if the user is in a role you simply query the IsInRole method of the current user. Let's look at the code snippet responsible for displaying the link to create a new forum post: If Not (User.IsInRole("Public")) And Not (User.IsInRole("Other")) Then ' Display the link Else ' Don't display it!

End If Or said in another manner: If Not (Thread.CurrentPrincipal.IsInRole("Public")) _ And Not (Thread.CurrentPrincipal.IsInRole("Other")) Then ' Display the link Else ' Don't display it! End If Imperatively You can also imperatively demand that a user be in a role to access code by creating an instance of the PrincipalPermission class, configuring it with the user and role that you are checking for, then call the Demand method of that object to do the check. If the check fails, a SecurityException is raised. This is the previous example re-written to use imperative checking: Dim objPermission As New PrincipalPermission(User.Identity.Name, "manager") Try objPermission.Demand() Catch ex As SecurityException ' Don't display it! End Try The downside to the two previous methods is that if you are calling a method several times from different parts of the application, you need to repeat this logic all over the place. Declaratively As many of you would know, one of the great benefits of using Stored Procedures in the database is that you can enforce permissions specific to an individual stored procedure. With declarative checks you can bind permissions to an actual method (or event, or whatever) using meta-data attached to each specific object that requires it. For our purposes, let us assume that we have a method called dismissModerator(). Now, for obvious reasons, we do not want the moderator, or anyone else for that matter, to be able to call this method! Therefore, only users who are in the role of System Administrator can access this method. Let's set it up: ' Create a method that disables all moderator permissions ' and attach a PrincipalPermissionAttribute to it that issues ' a Demand. <PrincipalPermissionAttribute(SecurityAction.Demand, Name:="smith", Role:="SysAdmin")> _ Public Sub DismissModerator() ' logic here End Sub

And now, to call it: Try DismissModerator() Catch ex As SecurityException ' do something else End Try What has happened here is that the Permission check that is bound to the DismissModerator() Sub is carried out before execution of the Sub takes place. As you can see, this method of authorization is good, because you are enforcing the policy on an actual object, meaning that a developer cannot accidentaly call the method and inadvertently dismiss the poor forum moderator, because the object itself does the role checking. You can enforce declarative checking at class, class member, property or even event level. If you define a permission attribute on a class as well as one of its members the declaration at member level overrides the declaration at class level. Summary In this article we've had a brief look at what role based security is and how the .NET runtime can assist in implementing it in our solutions. If you found this article interesting I'd encourage you to delve further into the System.Security.Permissions namespace where you'll find even more classes to assist you in producing a customized solution. Pay particular attention to the Union method of the PrincipalPermission class which allows you to bind multiple principal permissions to create a new permission. Creating your own roles ' Global.asax event handler that fires upon attempting to authenticate the user Sub Application_AuthenticateRequest(ByVal sender As Object, ByVal e As EventArgs) If Request.IsAuthenticated() Then ' create an array of roles for the current user ' these would most likely be dynamically read ' from the data store for each user. Dim arrRoles() As String = {"Manager", "Cleaner"} ' Add our Principal to the current context Thread.CurrentPrincipal = New GenericPrincipal(Context.User.Identity, arrRoles) End If End Sub This only needs to be done once because the runtime automatically copies a reference to the principal object from the calling thread to the CallContext of the new thread.

If you cast your mind back to how FormsAuthentication works, you will remember that a user is authenticated and then an authentication cookie attached to the validating Response when you call one of the appropriate static methods of the FormsAuthentication provider. It is at that moment that the Application_AuthenticateRequest handler is called. When authenticating users you do not have to do anything in this handler, nor do you need to explicitly create a new instance of the GenericPrincipal class. However, to dynamically assign custom roles to a user (which is what we are interested in today) you do need to, and the Application_AuthenticateRequest handler is the ideal place to do this. Bringing it All Together I'll stop here briefly, before we move onto the really cool stuff, to summarize the five steps needed to allow your application to implement role based checking: 1. Validate the User - check the users credentials against a data store of credentials. 2. Create an Identity Dim objIdentity As GenericIdentity = New GenericIdentity("txtUsername") 3. Get the roles for the current user Dim strRoles() As String Dim arrRoles As New ArrayList() ' do some database call that returns a reader While reader.Read() arrRoles.Add(reader("role")) End While strRoles = arrRoles.ToArray(GetType(String), String()) 4. Add the Identity and the Roles to a Principal Dim objPrincipal As GenericPrincipal = New GenericPrincipal(objIdentity, strRoles) 5. Add the Principal to the current context of the current thread Thread.CurrentPrincipal = objPrincipal Using Roles Once you have authenticated a user and defined their identity and roles there are four ways that you can interact with the Principal to enforce permissions based on memberships within the application: 1. 2. 3. 4. Configuratively Programmatically Imperatively Declaratively

Configuratively You can configure the authorization and/or the location elements within the

Web.config configuration files to grant or deny access to entire areas within the application outright, as opposed to the other 3 methods which suit a more piecemeal approach. For example, in the application that we are developing it may be necessary to ensure that only users acting as System Administrators or Moderators are allowed access to certain administrative screens. To demonstrate this, let's presume that all of the forms that allow users to moderate forum posts reside under a directory called "ForumAdmin". Rather than programatically checking the role of a user inside every file that sits in that directory, you can simply configure the Web.config file for that folder to do the checking for you. The following snippet excludes all users except for System Administrators or Moderators from accessing files in the directory that the Web.config file resides in (as well as its subdirectories): ' Snippet from Web.config <authorization> <deny users="*" /> <allow roles="SysAdmin, Moderator" /> </authorization> By placing the abovementioned Web.config at the root of the ForumAdmin directory, the application itself will inspect the roles of the user making the Request to determine whether access is granted. That's right, no additional code is neccessary, regardless of how many .aspx files are placed under that folder. (Compare that to classic ASP and the Session-based approach, where every "sensitive" page needs to have a check at the top of the page to determine if the user has rights to view the page...) Even from this simple example, you should get an idea of how this new approach simplifies the task of authorization, and, how it supersedes the methods available under the current practices of classic ASP. Programmatically Alternatively, you may have directories that contain files that will be accessed by users acting in a wide variety of roles. An example of this would be the directory that displays the actual forum itself. You need to allow viewing access to all areas of the forum, even to unauthenticated members of the public, but to create a new post, it is imperative that a user not be in the role of Public or Other. In your code, whenever you need to check to see if the user is in a role you simply query the IsInRole method of the current user. Let's look at the code snippet responsible for displaying the link to create a new forum post: If Not (User.IsInRole("Public")) And Not (User.IsInRole("Other")) Then ' Display the link Else ' Don't display it!

End If Or said in another manner: If Not (Thread.CurrentPrincipal.IsInRole("Public")) _ And Not (Thread.CurrentPrincipal.IsInRole("Other")) Then ' Display the link Else ' Don't display it! End If Imperatively You can also imperatively demand that a user be in a role to access code by creating an instance of the PrincipalPermission class, configuring it with the user and role that you are checking for, then call the Demand method of that object to do the check. If the check fails, a SecurityException is raised. This is the previous example re-written to use imperative checking: Dim objPermission As New PrincipalPermission(User.Identity.Name, "manager") Try objPermission.Demand() Catch ex As SecurityException ' Don't display it! End Try The downside to the two previous methods is that if you are calling a method several times from different parts of the application, you need to repeat this logic all over the place. Declaratively As many of you would know, one of the great benefits of using Stored Procedures in the database is that you can enforce permissions specific to an individual stored procedure. With declarative checks you can bind permissions to an actual method (or event, or whatever) using meta-data attached to each specific object that requires it. For our purposes, let us assume that we have a method called dismissModerator(). Now, for obvious reasons, we do not want the moderator, or anyone else for that matter, to be able to call this method! Therefore, only users who are in the role of System Administrator can access this method. Let's set it up: ' Create a method that disables all moderator permissions ' and attach a PrincipalPermissionAttribute to it that issues ' a Demand. <PrincipalPermissionAttribute(SecurityAction.Demand, Name:="smith", Role:="SysAdmin")> _ Public Sub DismissModerator() ' logic here End Sub

And now, to call it: Try DismissModerator() Catch ex As SecurityException ' do something else End Try What has happened here is that the Permission check that is bound to the DismissModerator() Sub is carried out before execution of the Sub takes place. As you can see, this method of authorization is good, because you are enforcing the policy on an actual object, meaning that a developer cannot accidentaly call the method and inadvertently dismiss the poor forum moderator, because the object itself does the role checking. You can enforce declarative checking at class, class member, property or even event level. If you define a permission attribute on a class as well as one of its members the declaration at member level overrides the declaration at class level. Summary In this article we've had a brief look at what role based security is and how the .NET runtime can assist in implementing it in our solutions. If you found this article interesting I'd encourage you to delve further into the System.Security.Permissions namespace where you'll find even more classes to assist you in producing a customized solution. Pay particular attention to the Union method of the PrincipalPermission class which allows you to bind multiple principal permissions to create a new permission.

ASP.NET 2.0 The Provider Model If you've downloaded and used the ASP.NET Starter Kits available from www.asp.net, the Provider Model and its implementation probably won't have come as too much of a shock. Microsoft began to employ the "Provider Design Pattern" in its Starter Kits in the summer of 2002, but didn't officially formalize it as a model until the development of ASP.NET 2.0's Personalization feature. Without boring you with the specifics, let me generalize by saying that because of the Provider Model, security in ASP.NET 2.0 is much more simplistic, easy to configure, and quick to implement than it was previously. The model assumes the configuration of users and roles by automatically creating a database within SQL Server (or, if you choose

to use Access, as an .MDB file within the Data folder of your application). Immediately, you're able to start to register and authenticate users against this newly created table. Gone are the days of having to build the database schema by hand, and then having to tailor each Web application to work in its respective database schema. The Provider Model can be broken into two distinct security providers: the Membership Provider and the Role Provider. The Membership Provider is used to store usernames and passwords; the Role Provider is used to store -- you guessed it -- user roles. Out of the box membership providers include the default AccessMembershipProvider, the SqlMembershipProvider, and an abstract MembershipProvider class. You can use this to create your own Membership Provider if, for instance, you need to store usernames and passwords within an XML file, or validate credentials via a Web service. For the sake of simplicity, we'll use the default AccessMembershipProvider throughout this article. The AccessMembershipProivder, like the SqlMembershipProvider, stores usernames and passwords within a database. The AccessMembershipProivder, however, stores this information within an Access database that's created for you automatically within the Data folder of your application. Whenever you create a new Web application, the AccessMembershipProivder automatically will create everything you need to start registering and authenticating users. Configure Security Using the Website Administration Tool Configuring your applications to use ASP.NET 2.0 security is a simple three-step process. First, we create a new Website within either Visual Studio 2005 beta or Visual Web Developer 2005 Express beta, and ensure that Website is turned into an application within IIS. Second, we use the Web Site Administration Tool to enable and configure security for the newly created application. Finally, we use controls available in the suite of Login controls to build the UI with which our users will interact.

To demonstrate this simplicity and, most importantly, flexibility, let's start by creating a new Website. Follow these steps: 1.Open either Visual Studio 2005 beta or Visual Web Developer 2005 Express beta. 2.Select File, New Web Site. 3.Select the ASP.NET Web Site Template. 4.Choose a Website name and path within the Location text box and click OK. For this article, I'll call mine Dorknozzle. 5.You may want to take this time to rename your default Web form login.aspx. 6.Now that the Website has been created, convert the site into an application. First, open IIS. 7.Next, expand your computer name, expand the Websites folder, expand the Default Web Site node, and locate your newly created site. 8.Right click the Website and choose Properties. 9.Select the Create button from the Directory tab and click OK. 10. Close IIS.

Now that your Web application has been created and configured, you're ready to enable and configure security via the Web Site Administration Tool. Again, the Web Site Administration Tool is nothing more than a set of pre-built ASP.NET 2.0 pages and resources that reside within the C:\Inetpub\wwwroot\aspnet_webadmin\2_0_40607 directory. To enable and configure security, open the Web Site Administration Tool for your newly created Web application: navigate to the application's URL and add the WebAdmin.axd file to the end of the URL. In my case, the URL string will look like this: http://localhost/Dorknozzle/WebAdmin.axd If you're using Visual Studio 2005 beta or Visual Web Developer 2005 Express beta, you can also select ASP.NET Configuration

from the Website menu. Either way, the Web Site Administration Tool will appear. Immediately switch to the Security tab. Your screen will look like this: 1387_image1 (click to view image)

As you can see, security is divided into three core groups within the Web Site Administration Tool: Users, Roles, and Access Rules. If you are new to configuring security within the Web Site Administration Tool, it may be easier to simply select the link that reads, "To configure security step by step, use the Security Setup Wizard". This launches the Security Setup Wizard's Welcome screen. To begin the configuration process, select the

Next button located near the bottom right of the browser window to advance to Step 2. Step 2 allows you to choose the authentication type. If you're using Windows authentication (default), simply click next. To work with Forms authentication (as we're doing in this article) click the "From the Internet" option and choose Next. Step 3 displays the default provider "AspNetAccessProvider" mentioned earlier in this article. Because the Access Provider is the default provider, we needn't configure this option here. Simply choose Next. Step 4 enables roles-based authentication for an application. If you were working with roles, you'd enable this checkbox and click Next. Configuration of roles would be handled within the Security tab in the main menu. For now, leave the checkbox unchecked and click Next. Step 5 is where the real fun begins. This is where you can add users to your application, auto-generate passwords, send the passwords via email, and activate the users. To keep this example simple, I'll enter some basic information, outlined below, and click Create User.

1387_image2 (click to view image)

Once you've added the user, you have the option to choose Continue, to create more users, or Next, to advance to the Next screen. I'll add two more users and then click Next. Step 6 allows you to configure rules to apply to particular users. For instance, since the user "zak" is an administrator, he'll be given full access. However, if I had various departments within my Web application, I could configure certain users to be allowed access only within their department folder. I won't configure any rules at this time, so I'll click Next. Step 7 alerts you that you've finished enabling and configuring security for your Web application. To complete the wizard,

select Finish -- you'll be taken back to the Security tab in the main menu. Now that you're done, you can go ahead and close the Web Site Administration Tool. Automatically, the AccessMembershipProvider creates a Microsoft Access database file called AspNetDB within your application's Data folder. Open the database file to examine its structure. As you can see below, ten tables are created, including the aspnet_Users table, which includes generic user information, and the aspnet_Membership table, which contains detailed user credential information including the user's hashed password and salt. 1387_image3 (click to view image)

For more information on hashing and salting passwords, see the SitePoint article, "Securing Passwords in Your Database". Using Login Controls As I mentioned earlier, some of the most exciting controls to be added to the collection of already-robust ASP.NET controls are contained in the suite known as the Login controls. The Login controls, which include the Login, LoginView, PasswordRecovery, LoginStatus, LoginName, CreateUserWizard, and ChangePassword controls, allow quick, seamless integration between ASP.NET 2.0 security and your Web applications. Tightly integrated with the Provider Model, Login controls take full advantage of the configured provider. For instance, if you configured your application to use the AccessMembershipProvider (which is the default), you could easily add to your page a Login control that would automatically validate a user against the AspNetDB Access database located within your applications Data folder. Alternatively, if you configured your application to use the SqlMembershipProvider, the configured Login controls would validate users against a SQL database instead. The Login Control Now that you have a grasp on the Provider Model, AccessMembershipProvider, and have enabled and configured your site via the Web Site Administration Tool to use authentication, let's build the UI with which your users can interact. As I've already mentioned, ASP.NET 2.0 includes a suite of Login controls spearheaded by the Login control. The Login control provides the necessary interface through which a user can enter their username and password. At its most basic level of functionality, a Login control can easily be added to the page. Just include the following markup within a Web form: <asp:Login id="lcDorknozzle" runat="server"/>

The control renders as a basic login page similar to that shown below. 1387_image4 (click to view image)

While the Login control exposes myriad properties, some of which I'll go over briefly, the great part of about it lies in the fact that only the DestinationPageUrl property really needs to be configured. When it's set, this property automatically redirects the user to a destination page. Knowing this, we could configure our Login control to resemble the following: <asp:Login id="lcDorknozzle" runat="server" DestinationPageUrl="index.aspx"/> In this case, if the users entered valid credentials, they would automatically be redirected to index.aspx. Other important

properties include the ability to offer a customized error message when users enter the wrong credentials. This property, the FailureText property, is by default set to read, "Your login attempt was not successful. Please try again." You may also want automatically to redirect the user to a page that allows them to create a new user or even recover a lost password. In this case, you would configure the CreateUserText, CreateUserUrl, PasswordRecoveryText, and PasswordRecoveryUrl properties as follows: <asp:Login id="lcDorknozzle" runat="server" DestinationPageUrl="index.aspx" CreateUserText="New User?" CreateUserUrl="newuser.aspx" PasswordRecoveryText="Forget Your Password?" PasswordRecoveryUrl="forgotpassword.aspx"/> In this case, the control would render in the browser similar to the image shown below.

1387_image5 (click to view image)

The flexibility of the Login control doesn't stop there. Aside from the dozens of other properties that can be used to customize the control's functionality, the Login control also supports Theming via the EnableTheming property, customized CSS classes via the CssClass property, and basic formatting through the dozens of style properties associated with each control available in the ASP.NET framework. In fact, if you're using either Visual Studio 2005 beta or Visual Web Developer 2005 Express beta, you can simply right-click the control, select Auto Format, and pick a style from a pre-defined list displayed in the Auto Format dialog box. I picked the Elegant style, which renders similarly to this:

1387_image6 (click to view image)

The LoginName and LoginStatus Control Once the user has logged in, you may want to utilize either the LoginName and/or LoginStatus control. These two useful controls allow you to display relevant information regarding the authentication status of a user. The LoginName control, for instance, allows you simply to display the username of the authenticated user: <asp:LoginName id="lnUser" runat="server"/> The LoginStatus control, on the other hand, allows the user to log in or log out of your application. It resembles the following: <asp:LoginStatus id=" lsUser" runat="server"/>

To see these controls in action, I'll add them to my index.aspx page (the page at which the user arrives once they've logged in): <form runat="server"> Welcome <asp:LoginName id="lnUser" runat="server"/>, your login was successful!<br /><br /> <asp:LoginStatus id="lsUSer" runat="server"/> </form> When users log in now, they are presented with a customized message that contains their names, along with the ability to log out if they choose. The output renders in the browser as shown below. 1387_image7 (click to view image)

The LoginStatus control will allow users to log out if they are currently logged in, and will display a link to the login page if they're logged out. The LoginView Control

Another useful Login control is the LoginView control. This control allows you to customize information that will be shown to users through templates, based on their roles. For instance, you may decide that Administrators are able to see a complete department list once they enter the application, but that someone who belongs to a specific department -- let's say it's Engineering -- only sees information that relates to the company and the Engineering department. You can also use the LoginView control to display customized information based on users' login status. For instance, if an anonymous user visits your site, you might want to alert them that the site is intended for registered users, and perhaps let them know that they can click the New User link to register. Alternatively, you may want to alert logged-in users that they don't need to log in again. You might even show them a "welcome back" message, complete with their name, using the LoginName control discussed earlier. To use the LoginView control, you would simply add the control to the page using the following syntax: <asp:LoginView id="lvDorknozzle" runat="server"> </asp:LoginView> Of course, without the use of templates, the control is fairly useless. In this case, we'll make sure that anonymous users are told to register by clicking the New User link, and that logged-in users see a notification that they've already been logged in. Add the following LoggedInTemplate and AnonymousTemplate child tags to the LoginView parent tag: <asp:LoginView id="lvDorknozzle" runat="server"> <LoggedInTemplate> Welcome <asp:LoginName id="lnUser" runat="server"/> </LoggedInTemplate> <AnonymousTemplate> Welcome to the Dorknozzle site!<br /> Please click on the New User link to register on our site.

</AnonymousTemplate> </asp:LoginView> Now, when users visit the login.aspx page for the first time, they are considered anonymous and are presented with the welcome message similar to the one shown here. 1387_image8 (click to view image)

You could configure the LoginView control further by displaying customized messages depending on users' roles. For instance, I could add within the LoginView tag the RoleGroups tag. To this, I'd add a

RoleGroup control in which the name of the Role was a value of the Roles attribute: <asp:LoginView ID="lvDorknozzle" Runat="server"> <RoleGroups> <asp:RoleGroup Roles="Engineering"> <ContentTemplate> You are a member of the Engineering department. </ContentTemplate> </asp:RoleGroup> </RoleGroups> <LoggedInTemplate> Welcome <asp:LoginName ID="lnUser" Runat="server" /> </LoggedInTemplate> <AnonymousTemplate> Welcome to the Dorknozzle site!<br /> Please click on the New User link to register on our site. </AnonymousTemplate> </asp:LoginView> The CreateUserWizard Control Chances are that if you went through the process of creating new users via the Web Site Administration Tool, you've already used the CreateUserWizard control and may not even have known it. The CreateUserWizard control simply allows a new user to add themselves (or register) to your Web application. This powerful tag offers many customizable features, but can quickly be added to and used in your site via the following tag: <asp:CreateUserWizard id="NewUserWiz" runat="server"> </asp:CreateUserWizard> In the browser, the page renders similar to that shown below.

1387_image9 (click to view image)

Of course, the true power in the CreateUserWizard control lies in its flexibility. The control offers seven templates (HeaderTemplate, SideBarTemplate, StartNavigationTemplate, StepNavigationTemplate, FinishNavigationTemplate, Sign Up For a New Account Template, and a Complete Template) that can be customized according to your needs. Even better, the CreateUserWizard control allows you automatically to send an email to newly registered users simply by adding the MailDefinition tag as follows:

<asp:CreateUserWizard id="CreateUserWizard1" runat="server"> <MailDefinition BodyFileName="NewUserEmail.txt" From="welcome@dorknozzle.com" Subject="Welcome to the Dorknozzle site!"/> </asp:CreateUserWizard> Once a new user is added to the site, an email is sent to that user. That email, defined within a text file, is loaded via the BodyFileName property, as shown in the code above. Variables can be customized simply with the addition of special expressions, such as <% UserName %>, to the text file. Finally, in order for the email to be relayed, the email server must be specified in the <smtpMail> mail section of the Web.config file: <configuration> <system.web> <authentication mode="Forms"/> <smtpMail serverName="Localhost"/> </system.web> </configuration> The PasswordRecovery Control As an administrator of a Web application, the last things you want to do are answer phone calls and respond to emails for people who have forgotten their passwords. The PasswordRecovery control can ease this burden. By default, you can add the following tag, which allows users to enter their user names and answer their secret questions. In turn, an email message is generated with each user's password, and sent: <asp:PasswordRecovery id="prForgotPass" runat="server"> </asp:PasswordRecovery> In the browser, the PasswordRecovery control renders like so:

1387_image10 (click to view image)

Once users enter valid user names, they must answer their secret questions. In the browser, the page looks like that shown below.

1387_image11 (click to view image)

Similar to the CreateUserWizard control, the mail formatting is handled within the MailDefinition tag: <asp:PasswordRecovery id="prForgotPass" runat="server"> <MailDefinition BodyFileName="forgotpassword.txt" From="helpdesk@dorknozzle.com" Subject="Word has it, you forgot your password?"/> </asp:PasswordRecovery> If everything is formatted correctly, the email will be sent and a message will appear to the user similar to this:

1387_image12 (click to view image)

The ChangePassword Control Finally, The ChangePassword control, as you might expect, allows users to change their passwords. The ChangePassword control can be added to any page with the following tag: <asp:ChangePassword id="cpChangePass" runat="server"/> In the browser, the control renders similar to this:

1387_image13 (click to view image)

Like the CreateUserWizard and PasswordRecovery controls, the ChangePassword control can be configured, via the MailDefinition tag, to send a confirmation email to users once they've successfully changed their passwords. Unlike the CreateUserWizard and PasswordRecovery controls, however, the ChangePassword control requires that users are logged in before they can change their passwords. The Membership API In certain instances when working with security, you'll need more flexibility than is provided either by the Web Site Administration Tool or the Login controls. In this case, you'll want to work directly with the Membership API. Exposed through the Membership class, the Membership API allows you to create users, change passwords, and search for users based on specific criteria, programmatically. For the

most part, the Login controls we've seen so far use the methods exposed by the Membership class anyway; your ability to use these directly from code is an added bonus. The following methods exposed by the Membership class are the ones you may find yourself using most often:
CreateUser - Allows you to creates new users DeleteUser - Allows you to delete existing users FindUsersByEmail - Allows you to retrieve a set of users that

match an email address


FindUsersByName - Allows you to retrieve a set of users that

match a certain username


GeneratePassword - Allows you to generate a random password GetAllUsers - Allows you to retrieve all users stored in the

Membership Provider
GetNumberOfUsersOnline - Allows you to return the number of

users currently logged on


GetUser - Allows you to retrieve the membership information

associated with the current or supplied user


GetUsernameByEmail - Allows you to retrieve a username for a

user with a certain email address


UpdateUser - Allows you to update a particular user's

information
ValidateUser - Allows you to authenticate a user against the

Membership Provider To demonstrate the flexibility of these methods, I'll add some text and a Label control to my index.aspx as follows: Number of Users Online: <asp:Label id="lblNumUsersOnline" runat="server"/> In my code-behind, I'll add some code that accesses the number of users online:

Sub Page_Load(s As Object, e As EventArgs) Handles MyBase.Load lblNumUsersOnline.Text = _ Membership.GetNumberOfUsersOnline().ToString() End Sub I could also add a GridView control to the page like so: <asp:GridView id="gvUsers" runat="server" AutoGenerateColumns="False"> <Columns> <asp:BoundField HeaderText="Username" DataField="Username" /> <asp:BoundField HeaderText="Is Online?" DataField="IsOnline" /> <asp:BoundField HeaderText="Is Approved?" DataField="IsApproved" /> <asp:BoundField HeaderText="Email" DataField="Email" /> </Columns> </asp:GridView> In the code-behind, I could add the following to my Page_Load event handler to fill the grid: gvUsers.DataSource = Membership.GetAllUsers() gvUsers.DataBind() The output renders in the browser similar to the below.

1387_image14 (click to view image)

Conclusion ASP.NET 2.0 builds on an already feature-rich framework by adding enhanced security features. In this article, we focused on the new Provider Model exposed by the .NET Framework 2.0. Next, we looked at the suite of Login controls that you can take advantage of when building your Web applications. Finally, we looked at the Membership API and the methods exposed by the Membership class. Whether you use

some or all of the security features offered within the newest release of ASP.NET is up to you, but I, for one, think there's a great deal to be excited about in ASP.NET 2.0.

Das könnte Ihnen auch gefallen