Now that you understand the process behind forms authentication, we need to add it to our application. The process will be slightly different because we already have a database to use, but without the ASP.NET membership schema. We'll add that to the database and then create some user accounts and membership roles to handle the security for our application. We'll also secure some of our content and add a menu to our Master Page to navigate between the pages of our Content Management System.
Preparing an existing SQL database
As we have an existing database, we can't create a new database for our membership and authentication system. Well, actually we could, but using a second database is problematic when we upload the application to a host because many web hosting companies allow only a single database under the hosting plan. Besides, we can easily add the membership schema the same way we did earlier in the article with our empty database, using aspnet_regsql.exe. Previously we used the wizard, this time we'll use the command line. If you take a look at the database in SQL Server Management Studio Express now, before we execute the command to add the schemas, you should see the few tables that were already created, as shown below:
The aspnet_regsql.exe tool
Using the command line, the executable is simple, as long as you know the command line arguments. The syntax and command arguments for aspnet_regsql.exe are available online at http://msdn.microsoft.com/en-us/library/x28wfk74.aspx. The following table shows the arguments we will use:
What we use
The server name
The database username
The database password
The database name
The schema functions to install
Our command line will look like this (all one line):
aspnet_regsql.exe -S .SQLEXPRESS -U sa -P SimpleCMS -d SimpleCMS_
Database -A all
To run the command line, go to Start | Run and enter cmd in the Run dialog box. Press Enter and you will be at a command prompt. Type cd C:WINDOWSMicrosoft.NETFrameworkv2.0.50727 and press Enter again, and you will be in the correct folder to find aspnet_regsql.exe. Note that you may need to change the path if your ASP.NET framework files are in a different location. Type the command line above and press Enter, and you should see that the command completed successfully, with a dialog similar to that below:
Now that we have executed the aspnet_regsql.exe command line, if you look at the database tables in SQL Server Management Studio Express, you should see the added table for the users, membership, and roles we will use in our application.
Earlier in the article, we created a single user account for accessing protected content. In a real-world environment, we would normally have many user accounts, way too many to add each account to each page we wanted to protect. Fortunately, the ASP.NET framework provides us with membership roles that we can place user accounts in, allowing us to define our access by role, not by user account. But first, we need some user accounts.
Let's start by creating three accounts in our application - User1, User2, and Administrator. Open the SimpleCMS web site in Visual Web Developer 2008 Express. Use the downloadable code provided for Chapter 4 of this book, it has the web.config file modified similar to what we did when we walked through the forms authentication demo earlier in the chapter. Open the Web Site Administration Tool by clicking on Website and then ASP.NET Configuration.
If you click on the Security tab, you will see that we have no users configured for this application. As you did earlier in the article, click on Create User and create the three users with user names of User1, User2, and Administrator. Use Password! as the password for each, and provide a valid email address for each (they can have the same email for testing). Also, provide a question and answer such as Favorite Color? and Blue. You can use the same question and answer for all three accounts if you wish. Each user entry should look something like the following:
If you return to the Security tab, you will notice that we have three user accounts, but no roles for those accounts. Let's add them next.
ASP.NET membership roles provide the ability to group many individual accounts into a single role to provide access to a resource such as a page or application. Changing access for an individual user then becomes a simple task of assigning them to or removing them from the appropriate role. A single user account can belong to multiple roles to provide extremely granular access to the application resources if your security demands are extensive.
To add roles to our application, we first need to enable roles. On the Security tab of the Web Site Administration Tool, under Roles, you should see a link to enable roles. Enabling roles consists of simply adding the following line to the web.config file in the system.web section:
<roleManager enabled="true" />
Similar to the membership provider we created earlier, roles require a role provider. We need to add this provider to the role manager, so edit the web.config roleManager section to read:
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
This adds an AspNetSqlRoleProvider that uses our connection string to the SimpleCMS database. At this point we have no roles defined, so let's create a few. Open the Web Site Administration Tool. If it's already open, you may need to close and reopen it because we modified the web.config file to add the role provider. Now, open the Security tab. In the Roles section, click on Create or manage roles.
Let's create an administration role first. We'll need it to secure areas to just administrative access. Simply enter Administrator, click on Add Role, and you'll see the new role in the list. Add roles for Author, Editor, and Registered User in the same manner. The roles list should look something like the following figure when you finish:
Adding users to roles
Once we have users and roles created, we need to assign users to roles. To do this, use the Security tab of the Web Site Administration Tool, under the Users section, to manage users. You'll see a list of user accounts, in our case all three of them, along with the ability to edit the user, delete the user, and edit the user's roles. Click on Edit roles next to the Administrator user and you'll see a checkbox list of user roles this account can be added to. Any roles currently assigned to the user will be checked. As there are currently none, check the Administrator role, and the Administrator user will be immediately added to the Administrator role, as shown below:
If you were to look at the database tables that hold the user accounts and roles, you would see something like this for the users:
Similarly, the roles would look like this:
You'll note that both the users and the roles contain an ApplicationID that defines what application these users and roles belong to, and that each user or role is identified by a UserID or RoleID. These are automatically created by the ASP.NET membership framework and are globally unique identifiers (GUIDs), which ensure that the specific user or role is unique across all possible applications and uses of this specific database store.
You would also find in the database a table that identifies users in roles, looking something like this:
You'll notice that this is a joining table, used in a database when there is a many-to-many relationship. Many users can belong to a role and a user can belong to many roles, thus the use of this table. You'll also notice that the database table uses the UserID and RoleID, making it very hard to simply look at this table directly to find what users are assigned to what roles. Fortunately, with the ASP.NET framework, you're isolated from having to work directly with the database, as well as relieved from having to create it and the code needed to access it.
We'll create the login page the same way we did with our demo application. Open the site in Visual Web Developer 2008 Express and add a new item to the application. Choose Web Form as the template and name it Login.aspx. Select the SimpleCMS.master as your Master Page and add the login code to the Content2 content placeholder control as done before. Your login page should look very similar to our demo application.
New user registration
Previously, we added user accounts to the database through the Web Site Administration Tool. This becomes impractical in our application for two reasons. The first reason is that the Web Site Administration Tool is not designed to work outside of the same system the site is hosted on. This makes using our application on a web host problematic. The second is that we really don't want to manually enter every user into the system, that's too much work. The ASP.NET framework makes life easy for us through the CreateUserWizard control, allowing users to add their own information to the user database and thus sign up for accounts on our system.
To add the CreateUserWizard to our login page, add the following code inside the Content2 content placeholder control, immediately below the login control we added:
<asp:CreateUserWizard ID="CreateUserWizard1" runat="server">
<asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server">
<asp:CompleteWizardStep ID="CompleteWizardStep1" runat="server">
If you run the page in your browser, you should see something like:
You'll notice the same login control we used in our demonstration application, plus a new control that allows a user to sign up for an account. The CreateUserWizard control reads the Membership settings from our web.config file and populates the control accordingly. In our case, it asks for the user name, password, email, and both the security question and answer. This control also provides client side validation of the entries, requiring that each text box have an entry before submitting the form, and validating that the password entered meets the password requirements for our application.
Go ahead and sign up a new user, entering all the required fields and clicking on Create User. You should get a page similar to the one shown next, indicating that the user account has been successfully created.
Naturally, we want to create a more appropriate design for this page and these controls. It would help them look better and be more intuitive for users who want to register a new account, versus those who already have an account and wish to login. One of the simplest ways to do this is to open the Design View of the login.aspx page in Visual Web Developer 2008 Express, right-click on the Login control, and then choose Autoformat. Pick a format such as Classic, and your control will automatically take on that format. Doing the same with the CreateNewUser control should look similar to:
If you open the code for the login.aspx page, you'll see the formatting for the controls has been added automatically.
Okay, our application now has user accounts and roles for those users, but just how do we use them to secure the content in our content management system? In our demonstration, we secured entire pages and restricted access to those pages to specific accounts. But in our Content Management System, we want to secure the content itself, not the page. And if content is secure, we want to let our users know that they need to create an account and login to see the content.
Let's begin by requiring users to have an active account to view an article from our database. Open the Default.aspx file in Visual Web Developer 2008 Express, and look at the FormView control that displays our article using the ArticlesBLL class, which in turn uses the DataSet1TableAdapters class. We don't want to change the functionality of that code, we just want that code to be available only to those users who have logged into our application. To do this, we'll use a LoginView control.
Change the FormView control section to the following code:
<asp:FormView ID="FormView1" runat="server">
<asp:LoginView ID="LoginView1" runat="server">
<p>We're sorry, this article requires you to have an
account and be logged in to view the article.
<p><a href="login.aspx">Register or Login</a><br /></p>
<asp:Label ID="Label1" runat="server"
Text='<%# Bind("ArticleName") %>'>
<asp:Label ID="Label2" runat="server"
Text='<%# Bind("Article") %>'>
The LoginView control shown here has two templates - an AnonymousTemplate and a LoggedInTemplate.These do just what they indicate, provide the the user the information that is laid out in the appropriate template, either Anonymous or LoggedIn Template, based on their current login status. If you run the page in your browser, you should see the following:
If you then click on the Register or Login link, and log in as a registered user, you should see the Default.aspx page complete with the article from the database.
There is an even more elegant way to handle login requirements in the ASP.NET 2.0 framework via the LoginStatus control, similar to what we did in our demo application. We can use it to add a login link to every page, so we don't have to build a login link into all the LoginView controls we might add to our application. This control displays a login or logout link, according to the logged in status of a user. This means if a user is not logged in, we will automatically show them a link to do so. That link will take them to the login page we created earlier.
Open the SimpleCMS.master Master Page file in Visual Web Developer 2008 Express. At the bottom of the page, you will find the copyright statement we added earlier. Immediately below that line, add this code of the LoginStatus control:
<asp:LoginStatus ID="LoginStatus1" runat="server" />
That's it, everything we need to add a login link on every page in our application. We can go back and delete the line from our Default.aspx LoginView that reads:
<p><a href="login.aspx">Register or Login</a><br /></p>
If you then view the Default.aspx page in a browser, it should look like the following figure when you are not logged in:
The Login link is automatically displayed on any page where the user is not logged in because it is part of our Master Page. If a user is already logged in, the link simply changes to a Logout link.
A major headache with almost any web site on the internet that requires registration is that you often do not want to, or even cannot, use the same password as you do on other sites. This results in most users having multiple passwords, and most users forgetting at least some of those passwords. The ASP.NET 2.0 framework has a PasswordRecovery control for just this purpose. Let's go ahead and add it to our application.
In Visual Web Developer 2008 Express, add a new web form with the name ForgotPassword.aspx and the select the SimpleCMS.master page Master Page file. In the Content2 ContentPlaceholder control, add the following code:
<asp:PasswordRecovery ID="PasswordRecovery1" Runat="server">
Open the Design View for this page, and AutoFormat the control to the same Classic format we used in the other login controls.
To link to this page, we'll use a LinkButton control on the login.aspx page. Open the page and add this code after the Login control:
<asp:LinkButton ID="LinkButton1" runat="server"
Save these files and when you run the login.aspx page in the browser, you should see the Forgot Password? link below the login control. Clicking on that link will show our ForgotPassword.aspx page, which looks like this:
A user entering their login name will then be presented with their challenge question and must answer it to receive their password. A correct answer results in the user receiving an email, containing his/her password, to his/her account. At this point, you will receive an error if you try to recover your password because we have not set up any email capability in our application.
In this two-part article, you learned how to configure ASP.NET forms authentication, along with how to provide controls for users to log in, as well as ways to secure the content displayed on the pages. We used the aspnet_regsql.exe utility to create the database for membership and authentication. We also used the ASP.NET Configuration utility to configure some authentication parameters for our web application, add users and roles, and assign users to roles. We also created pages that were secured from access by unauthorized users .
When we added these features to our application, we expanded our login page to allow users to register a new account and even to recover a password if they forgot it. We used the Login and CreateNewUser controls, which are built into the ASP.NET 2.0 framework, and we used the AutoFormat option to format these controls as the user will see them. We also used the LoginView control to restrict access to an article on our page, as well as the LoginStatus control to add a login link to all of our pages through our master Page.
If you are interested in more depth on the ASP.NET membership controls, you should check out the MSDN Patterns and Practices information at http://msdn.microsoft.com/en-us/library/ms998347.aspx. You will also find more information in the online tutorials at http://www.asp.net/learn/security/.
If you have read this article you may be interested to view :