You can use the ASP.NET Login
controls to build a user registration system for your website easily. You can use the Login
controls to display user registration forms, login forms, change password forms, and password reminder forms.
By default, the Login
controls use ASP.NET Membership to authenticate users, create new users, and change user properties. When you use the Login
controls, you are not required to write any code when performing these tasks.
In the first part of this chapter, you are provided with an overview of the Login
controls. You learn how to password-protect a section of your website and enable users to register and log in to your website.
In the remainder of this chapter, you learn how to use each of the following Login
controls in detail:
Login
—. Enables you to display a user login form.
CreateUserWizard
—. Enables you to display a user registration form.
LoginStatus
—. Enables you to display either a log in or log out link, depending on a user’s authentication status.
LoginName
—. Enables you to display the current user’s registered username.
ChangePassword
—. Enables you to display a form that allows users to change their passwords.
PasswordRecovery
—. Enables you to display a form that allows a user to receive an email containing his or her password.
LoginView
—. Enables you to display different content to different users depending on the user’s authentication status or role.
You won’t have any fun using the Login
controls unless you have confidential information to protect. Therefore, let’s start by creating a page that needs password protection.
Create a new folder in your application named SecretFiles and add the page in Listing 20.1 to the SecretFiles folder.
Example 20.1. SecretFilesSecret.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Secret</title> </head> <body> <form id="form1" runat="server"> <div> <h1>This Page is Secret!</h1> </div> </form> </body> </html>
There is nothing special about the page in Listing 20.1. It just displays the message This Page is Secret!
.
To password-protect the Secret.aspx
page, you need to make two configuration changes to your application: You need to configure both authentication and authorization.
First, you need to enable the proper type of authentication for your application. By default, Windows authentication is enabled. To use the Login
controls, you need enable Forms authentication by adding the web configuration file in Listing 20.2 to the root of your application.
The web configuration file in Listing 20.2 contains an authentication element that includes a mode
attribute. The mode
attribute has the value Forms
.
Authentication and authorization is discussed in more detail in Chapter 21, “Using ASP.NET Membership.”
By default, all users have access to all pages in an application. If you want to restrict access to the pages in a folder, then you need to configure authorization for the folder.
If you add the web configuration file in Listing 20.3 to the SecretFiles folder, then anonymous users are prevented from accessing any pages in the folder.
The web configuration file in Listing 20.3 contains an authorization element. This element contains a list of authorization rules for the folder. The single authorization rule in Listing 20.3 prevents anonymous users from accessing pages in the folder (the ? represents anonymous users).
If you prefer, you can use the Web Site Administration Tool to configure authentication and authorization. This tool provides you with a form interface for performing these configuration changes. When using Visual Web Developer, you can open the Web Site Administration Tool by selecting the menu option Website, ASP.NET Configuration.
If you attempt to request the Secret.aspx
page after adding the web configuration file in Listing 20.3, then you are redirected to a page named Login.aspx
automatically. Therefore, the next page that we need to create is the Login.aspx
page. (By default, this page must be located in the root of your application.)
The Login.aspx
page in Listing 20.4 contains a Login
control. The Login
control automatically generates a login form (see Figure 20.1).
Example 20.4. Login.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Login</title> </head> <body> <form id="form1" runat="server"> <div> <asp:Login id="Login1" CreateUserText="Register" CreateUserUrl="~/Register.aspx" Runat="server" /> </div> </form> </body> </html>
Notice that the Login
control includes a CreateUserText
and CreateUserUrl
property. Adding these properties to the Login
control causes the control to display a link to a page that enables a new user to register for your application. The Login
control in Listing 20.4 links to a page named Register.aspx
. This page is contained in Listing 20.5.
Example 20.5. Register.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Register</title> </head> <body> <form id="form1" runat="server"> <div> <asp:CreateUserWizard id="CreateUserWizard1" ContinueDestinationPageUrl="~/SecretFiles/Secret.aspx" Runat="server" /> </div> </form> </body> </html>
The Register.aspx
page contains a CreateUserWizard
control. This control automatically generates a user registration form (see Figure 20.2). After you submit the form, a new user is created and you are redirected back to the Secret.aspx
page.
The default ASP.NET Membership provider requires you to create a password that contains at least seven characters, and at least one of the characters must be non-alphanumeric (not a letter and not a number). So, secret_ is a valid password, but not secret9. In the next chapter, you learn how to change these default passwords requirements.
That’s all there is to it. Notice that we have created a complete user registration system without writing a single line of code. All the messy details of storing usernames and passwords are taken care of by the ASP.NET Framework in the background.
The Login
control renders a standard user login form. By default, the Login
control uses ASP.NET Membership to authenticate users. However, as you’ll see in a moment, you can customize how the Login
control authenticates users.
The Login
control supports a large number of properties that enable you to customize the appearance and behavior of the control (too many properties to list here). The page in Listing 20.6 illustrates how you can modify several of the Login
control’s properties to customize the form rendered by the control (see Figure 20.3).
Example 20.6. ShowLogin.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <style type="text/css"> .login { width:250px; font:14px Verdana,Sans-Serif; background-color:lightblue; border:solid 3px black; padding:4px; } .login_title { background-color:darkblue; color:white; font-weight:bold; } .login_instructions { font-size:12px; text-align:left; padding:10px; } .login_button { border:solid 1px black; padding:3px; } </style> <title>Show Login</title> </head> <body> <form id="form1" runat="server"> <div> <asp:Login id="Login1" InstructionText="Please log in before accessing the premium section of our Website." TitleText="Log In" TextLayout="TextOnTop" LoginButtonText="Log In" DisplayRememberMe="false" CssClass="login" TitleTextStyle-CssClass="login_title" InstructionTextStyle-CssClass="login_instructions" LoginButtonStyle-CssClass="login_button" Runat="server" /> </div> </form> </body> </html>
The page in Listing 20.6 uses Cascading Style Sheets to change the appearance of the login form rendered by the Login
control. By taking advantage of Cascading Style Sheets, you can customize the appearance of the Login
control in any way that you can imagine.
For the complete list of properties supported by the Login
control, see the Microsoft .NET Framework SDK 2.0 documentation.
If you request a page that you are not authorized to view, then the ASP.NET Framework automatically redirects you to the Login.aspx
page. After you log in successfully, you are redirected back to the original page that you requested.
When you are redirected to the Login.aspx
page, a query string parameter named ReturnUrl
is automatically added to the page request. This query string parameter contains the path of the page that you originally requested. The Login
control uses the ReturnUrl
parameter when redirecting you back to the original page.
You need to be aware of two special circumstances. First, if you request the Login.aspx
page directly, then a ReturnUrl
parameter is not passed to the Login.aspx
page. In that case, after you successfully log in, you are redirected to the Default.aspx
page.
Second, if you add the Login
control to a page other than the Login.aspx
page, then the ReturnUrl
query string parameter is ignored. In this case, you need to set the Login
control’s DestinationPageUrl
property. When you successfully log in, you are redirected to the URL represented by this property. If you don’t supply a value for the DestinationPageUrl
property, the same page is reloaded.
Some websites display a login form at the top of every page. That way, registered users can log in at any time to view additional content. The easiest way to add a Login
control to all the pages in an application is to take advantage of Master Pages. If you add a Login
control to a Master Page, then the Login
control is included in every content page that uses the Master Page.
You can change the layout of the Login
control by modifying the Login
control’s Orientation
property. If you set this property to the value Horizontal
, then the Username and Password text boxes are rendered in the same row.
If you include a Login
control in all your pages, you should also modify the Login
control’s VisibleWhenLoggedIn
property. If you set this property to the value False
, then the Login
control is not displayed when a user has already authenticated.
For example, the Master Page in Listing 20.7 contains a Login
control that has both its Orientation
and VisibleWhenLoggedIn
properties set.
Example 20.7. LoginMaster.master
<%@ Master Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <style type="text/css"> html { background-color:silver; } .content { margin:auto; width:650px; border:solid 1px black; background-color:white; padding:10px; } .login { font:10px Arial,Sans-Serif; margin-left:auto; } .login input { font:10px Arial,Sans-Serif; } </style> <title>My Website</title> </head> <body> <form id="form1" runat="server"> <div class="content"> <asp:Login id="Login1" Orientation="Horizontal" VisibleWhenLoggedIn="false" DisplayRememberMe="false" TitleText="" CssClass="login" Runat="server" /> <hr /> <asp:contentplaceholder id="ContentPlaceHolder1" runat="server"> </asp:contentplaceholder> </div> </form> </body> </html>
The content page in Listing 20.8 uses the Master Page in Listing 20.7 (see Figure 20.4). When you open the page in a browser, the Login
control is hidden after you successfully log in to the application.
If you need to completely customize the appearance of the Login
control, then you can use a template. The Login
control includes a LayoutTemplate
property that enables you to customize the layout of the controls rendered by the Login
control.
When you create a Layout template, you can add controls to the template that have the following IDs:
You also need to add a Button
control that includes a CommandName
property with the value Login
.
The page in Listing 20.9 illustrates how you can use a LayoutTemplate
to customize the appearance of the Login
control (see Figure 20.5).
Example 20.9. LoginTemplate.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <style type="text/css"> .loginError { color:red; font:bold 14px Arial,Sans-Serif; } </style> <title>Login Template</title> </head> <body> <form id="form1" runat="server"> <div> <asp:Login id="Login1" Runat="server"> <LayoutTemplate> <asp:Label id="FailureText" EnableViewState="false" CssClass="loginError" Runat="server" /> <br /> <asp:Label id="lblUserName" AssociatedControlID="UserName" Text="User Name:" Runat="server" /> <br /> <asp:TextBox id="UserName" Runat="server" /> <br /><br /> <asp:Label id="lblPassword" AssociatedControlID="Password" Text="Password:" Runat="server" /> <br /> <asp:TextBox id="Password" TextMode="Password" Runat="server" /> <br /><br /> <asp:Button id="btnLogin" Text="Login" CommandName="Login" Runat="server" /> </LayoutTemplate> </asp:Login> </div> </form> </body> </html>
By default, the Login
control uses ASP.NET Membership to authenticate a username and password. If you need to change this default behavior, then you can handle the Login
control’s Authenticate
event.
Imagine, for example, that you are building a simple application and you want to store a list of usernames and passwords in the web configuration file. The web configuration file in Listing 20.10 contains the credentials for two users named Bill and Ted.
Example 20.10. Web.Config
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.web> <authentication mode="Forms"> <forms> <credentials passwordFormat="Clear"> <user name="Bill" password="secret" /> <user name="Ted" password="secret" /> </credentials> </forms> </authentication> </system.web> </configuration>
The page in Listing 20.11 contains a Login
control that authenticates users against the list of usernames and passwords stored in the web configuration file.
Example 20.11. LoginCustom.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> Sub Login1_Authenticate(ByVal sender As Object, ByVal e As AuthenticateEventArgs) Dim userName As String = Login1.UserName Dim password As String = Login1.Password e.Authenticated = FormsAuthentication.Authenticate(userName, password) End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Login Custom</title> </head> <body> <form id="form1" runat="server"> <div> <asp:Login id="Login1" OnAuthenticate="Login1_Authenticate" Runat="server" /> </div> </form> </body> </html>
Notice that the page in Listing 20.11 includes a method that handles the Login
control’s Authenticate
event. The second parameter passed to the Authenticate
event handler is an instance of the AuthenticateEventArgs
class. This class includes the following property:
Authenticated
If you assign the value True
to this property, then the Login
control authenticates the user.
In Listing 20.11, the FormsAuthentication.Authenticate()
method is called to check for a username and password in the web configuration file that matches the username and password entered into the login form. The value returned from this method is assigned to the AuthenticateEventArgs.Authenticated
property.
The CreateUserWizard
control renders a user registration form. If a user successfully submits the form, then a new user is added to your website. In the background, the CreateUserWizard
control uses ASP.NET membership to create the new user.
The CreateUserWizard
control supports a large number of properties (too many to list here) that enable you to modify the appearance and behavior of the control. For example, the page in Listing 20.12 uses several of the CreateUserWizard
properties to customize the appearance of the form rendered by the control.
Example 20.12. ShowCreateUserWizard.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <style type="text/css"> .createUser { width:350px; font:14px Verdana,Sans-Serif; background-color:lightblue; border:solid 3px black; padding:4px; } .createUser_title { background-color:darkblue; color:white; font-weight:bold; } .createUser_instructions { font-size:12px; text-align:left; padding:10px; } .createUser_button { border:solid 1px black; padding:3px; } </style> <title>Show CreateUserWizard</title> </head> <body> <form id="form1" runat="server"> <div> <asp:CreateUserWizard id="CreateUserWizard1" ContinueDestinationPageUrl="~/Default.aspx" InstructionText="Please complete the following form to register at this Website." CompleteSuccessText="Your new account has been created. Thank you for registering." CssClass="createUser" TitleTextStyle-CssClass="createUser_title" InstructionTextStyle-CssClass="createUser_instructions" CreateUserButtonStyle-CssClass="createUser_button" ContinueButtonStyle-CssClass="createUser_button" Runat="server" /> </div> </form> </body> </html>
The CreateUserWizard
control in Listing 20.12 is formatted with Cascading Style Sheets (see Figure 20.6). Notice that the control’s ContinueDestinationPageUrl
property is set to the value "~/Default.aspx"
. After you successfully register, you are redirected to the Default.aspx
page.
For the complete list of properties supported by the CreateUserWizard
control, see the Microsoft .NET Framework SDK 2.0 documentation.
By default, the CreateUserWizard
control displays the following form fields:
Username
Password
Confirm Password
Security Question
Security Answer
These are the default form fields. The last three fields are optional.
If you don’t want to require a user to enter either an email address or a security question and answer, then you need to modify the configuration of the default membership provider. The web configuration file in Listing 20.13 makes both an email address and security question and answer optional.
Example 20.13. Web.Config
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.web> <authentication mode="Forms" /> <membership defaultProvider="MyMembership"> <providers> <add name="MyMembership" type="System.Web.Security.SqlMembershipProvider" connectionStringName="LocalSqlServer" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" /> </providers> </membership> </system.web> </configuration>
If you add the web configuration file in Listing 20.13 to your application, then the CreateUserWizard
control does not render fields for a security question and answer. However, the CreateUserWizard
control still renders an email field. If you don’t want the email form field to be rendered, then you must perform an additional step. You must set the CreateUserWizard
control’s RequireEmail
property to the value False
.
If you add the page in Listing 20.14 to an application that contains the web configuration file in Listing 20.13, then the email, security question, and security answer form fields are not displayed (see Figure 20.7).
Example 20.14. CreateUserWizardShort.aspx
<%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>CreateUserWizard Short</title> </head> <body> <form id="form1" runat="server"> <div> <asp:CreateUserWizard id="CreateUserWizard1" RequireEmail="false" Runat="server" /> </div> </form> </body> </html>
You can set up the CreateUserWizard
control so that it automatically sends an email when a new user registers. For example, you can send an email that contains the new user’s registered username and password to that user’s email account.
Sending an unencrypted email across the Internet with a user’s password is dangerous. However, it also is a very common practice to include a password in a registration confirmation email.
The page in Listing 20.15 includes a MailDefinition
property that specifies the properties of the email that is sent to a user after the user successfully registers.
Example 20.15. CreateUserWizardEmail.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>CreateUserWizard Email</title> </head> <body> <form id="form1" runat="server"> <div> <asp:CreateUserWizard id="CreateUserWizard1" Runat="server"> <MailDefinition BodyFileName="Register.txt" Subject="Registration Confirmation" From="[email protected]" /> </asp:CreateUserWizard> </div> </form> </body> </html>
The MailDefinition
class supports the following properties:
BodyFileName
—. Enables you to specify the path to the email message.
CC
—. Enables you to send a carbon copy of the email message.
EmbeddedObjects
—. Enables you to embed objects, such as images, in the email message.
From
—. Enables you to specify the FROM
email address.
IsBodyHtml
—. Enables you to send an HTML email message.
Priority
—. Enables you to specify the priority of the email message. Possible values are High
, Low
, and Normal
.
Subject
—. Enables you to specify the subject of the email message.
The MailDefinition
associated with the CreateUserWizard
control in Listing 20.15 sends the contents of the text file in Listing 20.16.
Notice that the email message in Listing 20.16 includes two special expressions: <% UserName %>
and <% Password %>
. When the email is sent, the user’s registered username and password are substituted for these expressions (see Figure 20.8).
You can send a user’s password in an email message even when password is encrypted or hashed by the Membership provider.
The MailDefinition
class uses the email server configured by the smtp
element in the web configuration file. For example, the web configuration file in Listing 20.17 illustrates how you can configure the MailDefinition
class to use the local SMTP server included with Internet Information Services. (You can enable the local SMTP Server by opening Internet Information Services from the Administrative Tools folder.)
If you need to connect to a mail server located on another machine, you can use the web configuration file in Listing 20.18. In Listing 20.18, the smtp
element includes a network element that specifies a mail host, username, and password.
Example 20.18. Web.Config
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.net> <mailSettings> <smtp> <network host="mail.YourServer.com" userName="admin" password="secret" /> </smtp> </mailSettings> </system.net> <system.web> <authentication mode="Forms" /> </system.web> </configuration>
When you successfully log in from the Login.aspx
page, you automatically are redirected back to the original page you requested. The CreateUserWizard
control, on the other hand, does not redirect you back anywhere. If you want the CreateUserWizard
control to work in the same way as the Login
control, you need to write some code.
The Login
control in Listing 20.19 includes a link to a user registration page named CreateUserWizardReturn.aspx
. In the Page_Load()
event handler, the value of the ReturnUrl
query string parameter is added to the link to the registration page.
Example 20.19. LoginReturn.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) If Not Page.IsPostBack Then Dim dest As String = Request.QueryString("ReturnUrl") Login1.CreateUserUrl = "~/CreateUserWizardReturn.aspx?ReturnUrl=" & Server.UrlEncode(dest) End If End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Login Return</title> </head> <body> <form id="form1" runat="server"> <div> <asp:Login id="Login1" CreateUserText="Register" CreateUserUrl="~/CreateUserWizardReturn.aspx" Runat="server" /> </div> </form> </body> </html>
Before you use the page in Listing 20.19, you need to rename the page to Login.aspx
. If a user requests a page that the user is not authorized to access, then the user is automatically redirected to the Login.aspx
page. The ReturnUrl
parameter is automatically added to the request for Login.aspx
.
The page in Listing 20.20 contains a CreateUserWizard
control. This page also contains a Page_Load()
event handler. The value of the ReturnUrl
query string parameter is used to redirect the user back to the originally requested page.
Example 20.20. CreateUserWizardReturn.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> Sub Page_Load() If Not Page.IsPostBack Then Dim dest As String = "~/Default.aspx" If Not String.IsNullOrEmpty(Request.QueryString("ReturnURL")) Then dest = Request.QueryString("ReturnURL") CreateUserWizard1.ContinueDestinationPageUrl = dest End If End If End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>CreateUserWizard Return</title> </head> <body> <form id="form1" runat="server"> <div> <asp:CreateUserWizard id="CreateUserWizard1" Runat="server" /> </div> </form> </body> </html>
Some websites require you to complete multiple steps when registering. For example, you must complete the following steps when registering for a new account at eBay:
Complete the registration form.
Receive an email with a confirmation code.
Enter the confirmation code into a form.
This method of registration enables you to verify a user’s email address. If someone enters an invalid email address, then the confirmation code is never received.
If you need to implement this registration scenario, then you need to know about the following three properties of the CreateUserWizard
control:
AutoGeneratePassword
—. Enables the CreateUserWizard
control to generate a new password automatically.
DisableCreatedUser
—. Enables you to disable the new user account created by the CreateUserWizard
control.
LoginCreatedUser
—. Enables you to prevent a new user from being logged in automatically.
You can send two types of confirmation email messages. First, you can generate a new password automatically and send the password to the user. In that case, you’ll want to enable the AutoGeneratePassword
property and disable the LoginCreatedUser
properties.
Alternatively, you can allow a new user to enter her own password and send a distinct confirmation code in the confirmation email message. In that case, you’ll want to enable the DisableCreatedUser
property and disable the LoginCreatedUser
property. Let’s examine each of these scenarios in turn.
The page in Listing 20.21 contains a CreateUserWizard
control that does not render a password form field. The control has its AutoGeneratePassword
property enabled and its LoginCreatedUser
property disabled. After you complete the form rendered by the CreateUserWizard
control, you can click the Continue button to open the Login.aspx
page.
Example 20.21. CreateUserWizardPasswordConfirmation.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>CreateUserWizard Password Confirmation</title> </head> <body> <form id="form1" runat="server"> <div> <asp:CreateUserWizard id="CreateUserWizard1" CompleteSuccessText="A confirmation email containing your new password has been sent to your email address." AutoGeneratePassword="true" LoginCreatedUser="false" ContinueDestinationPageUrl="~/Login.aspx" Runat="server"> <MailDefinition From="[email protected]" BodyFileName="PasswordConfirmation.htm" IsBodyHtml="true" Subject="Registration Confirmation" /> </asp:CreateUserWizard> </div> </form> </body> </html>
Don’t set the membership provider’s passwordStrengthRegularExpression
attribute when enabling the CreateUserWizard
control’s AutoGeneratePassword
property.
The CreateUserWizard
control in Listing 20.21 sends the email message contained in Listing 20.22.
Example 20.22. PasswordConfirmation.htm
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head> <title>Password Confirmation</title> </head> <body> Your new password is <% Password %>. </body> </html>
The email message in Listing 20.22 includes the automatically generated password. When the new user receives the automatically generated password in her inbox, she can enter the password in the Login.aspx
page.
In the second scenario, the user gets to choose his password. However, the user’s account is disabled until he enters his confirmation code.
The CreateUserWizard
control in Listing 20.23 has its DisableCreateUser
property enabled and its LoginCreatedUser
property disabled.
Example 20.23. CreateUserWizardCodeConfirmation.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> Sub CreateUserWizard1_SendingMail(sender As object, e As MailMessageEventArgs) Dim user As MembershipUser = Membership.GetUser(CreateUserWizard1.UserName) Dim code As String = user.ProviderUserKey.ToString() e.Message.Body = e.Message.Body.Replace("<%ConfirmationCode%>", code) End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>CreateUserWizard Code Confirmation</title> </head> <body> <form id="form1" runat="server"> <div> <asp:CreateUserWizard id="CreateUserWizard1" CompleteSuccessText="A confirmation email containing your new password has been sent to your email address." DisableCreatedUser="true" ContinueDestinationPageUrl="~/ConfirmCode.aspx" OnSendingMail="CreateUserWizard1_SendingMail" Runat="server"> <MailDefinition From="[email protected]" BodyFileName="CodeConfirmation.htm" IsBodyHtml="true" Subject="Registration Confirmation" /> </asp:CreateUserWizard> </div> </form> </body> </html>
Notice that the page in Listing 20.23 includes a SendingMail
event handler. The confirmation code is the unique key assigned to the new user by the membership provider (a GUID). The confirmation code is substituted into the email message before the message is sent. The email message is contained in Listing 20.24.
Example 20.24. CodeConfirmation.htm
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head> <title>Code Confirmation</title> </head> <body> <%UserName%>, your confirmation code is <%ConfirmationCode%> </body> </html>
After you complete the form rendered by the CreateUserWizard
control, you can click the Continue button to open the ConfirmCode.aspx
page (see Figure 20.9).
Example 20.25. ConfirmCode.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> Sub btnConfirm_Click(ByVal sender As Object, ByVal e As EventArgs) Dim user As MembershipUser = Membership.GetUser(txtUserName.Text) If IsNothing(user) Then lblError.Text = "Invalid User Name" Else Dim providerCode As String = user.ProviderUserKey.ToString() Dim userCode As String = txtConfirmationCode.Text.Trim() If providerCode <> userCode Then lblError.Text = "Invalid Confirmation Code" Else user.IsApproved = True Membership.UpdateUser(user) Response.Redirect("~/SecretFiles/Secret.aspx") End If End If End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Confirm Code</title> </head> <body> <form id="form1" runat="server"> <div> <p> Enter the confirmation code that you received by email. </p> <asp:Label id="lblError" EnableViewState="false" ForeColor="Red" Runat="server" /> <br /><br /> <asp:Label id="lblUserName" Text="User Name:" AssociatedControlID="txtUserName" Runat="server" /> <br /> <asp:TextBox id="txtUserName" Runat="server" /> <br /><br /> <asp:Label id="lblConfirmationCode" Text="Confirmation Code:" AssociatedControlID="txtConfirmationCode" Runat="server" /> <br /> <asp:TextBox id="txtConfirmationCode" Columns="50" Runat="server" /> <asp:Button id="btnConfirm" Text="Confirm" OnClick="btnConfirm_Click" Runat="server" /> </div> </form> </body> </html>
If the user enters the correct username and confirmation code, then his account is enabled. The MembershipUser.IsApproved
property is assigned the value True
and the updated user information is saved with the Membership.UpdateUser()
method.
If you need to customize the appearance of the form rendered by the CreateUserWizard
control, then you can create templates for the CreateUserWizardStep
and the CompleteWizardStep
. For example, the page in Listing 20.26 displays a drop-down list to display options for the security question (see Figure 20.10).
Example 20.26. CreateUserWizardTemplate.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>CreateUserWizard Template</title> </head> <body> <form id="form1" runat="server"> <div> <asp:CreateUserWizard id="CreateUserWizard1" Runat="server"> <WizardSteps> <asp:CreateUserWizardStep> <ContentTemplate> <h1>Register</h1> <asp:Label id="ErrorMessage" ForeColor="Red" Runat="server" /> <br /><br /> <asp:Label id="lblUserName" Text="User Name:" AssociatedControlID="UserName" Runat="server" /> <br /> <asp:TextBox id="UserName" Runat="server" /> <br /><br /> <asp:Label id="lblPassword" Text="Password:" AssociatedControlID="Password" Runat="server" /> <br /> <asp:TextBox id="Password" TextMode="Password" Runat="server" /> <br /><br /> <asp:Label id="lblEmail" Text="Email:" AssociatedControlID="Email" Runat="server" /> <br /> <asp:TextBox id="Email" Runat="server" /> <br /><br /> <asp:Label id="lblQuestion" Text="Security Question:" AssociatedControlID="Question" Runat="server" /> <br /> <asp:DropDownList id="Question" Runat="server"> <asp:ListItem Text="Enter the name of your pet" Value="Pet Name" /> <asp:ListItem Text="Enter your favorite color" Value="Favorite Color" /> </asp:DropDownList> <br /><br /> <asp:Label id="lblAnswer" Text="Security Answer:" AssociatedControlID="Answer" Runat="server" /> <br /> <asp:TextBox id="Answer" Runat="server" /> </ContentTemplate> </asp:CreateUserWizardStep> <asp:CompleteWizardStep> <ContentTemplate> Your account was successfully created. </ContentTemplate> </asp:CompleteWizardStep> </WizardSteps> </asp:CreateUserWizard> </div> </form> </body> </html>
In the CreateUserWizardStep
, you can add controls with the following IDs:
Of course, you can add any other controls that you need. For example, you can request additional information when a new user registers and store the information in a separate database table (see the next section).
In the CreateUserWizardStep
, you also can add Button
controls that contain CommandName
properties with the following values:
CreateUser
Cancel
The CreateUserWizard
control inherits from the base Wizard
control. That means that you can use all the properties supported by the Wizard
control when using the CreateUserWizard
control. In particular, you can extend the CreateUserWizard
control with additional wizard steps.
For example, imagine that you want to require new users to enter their first and last names. The page in Listing 20.27 contains an additional WizardStep
that includes both first and last name form fields.
Example 20.27. CreateUserWizardExtra.aspx
<%@ Page Language="VB" %> <%@ Import Namespace="System.Data.SqlClient" %> <%@ Import Namespace="System.Web.Configuration" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> Sub CreateUserWizard1_CreatedUser(ByVal sender As Object, ByVal e As EventArgs) CreateUserProfile(CreateUserWizard1.UserName, txtFirstName.Text, txtLastName.Text) End Sub Private Sub CreateUserProfile(ByVal userName As String, ByVal firstName As String, ByVal lastName As String) Dim conString As String = WebConfigurationManager.ConnectionStrings("UserProfiles").ConnectionString Dim con As New SqlConnection(conString) Dim cmd As New SqlCommand("INSERT UserProfiles (UserName,FirstName,LastName) VALUES (@UserName,@FirstName,@LastName)", con) cmd.Parameters.AddWithValue("@UserName", userName) cmd.Parameters.AddWithValue("@FirstName", firstName) cmd.Parameters.AddWithValue("@LastName", lastName) Using con con.Open() cmd.ExecuteNonQuery() End Using End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>CreateUserWizard Extra</title> </head> <body> <form id="form1" runat="server"> <div> <asp:CreateUserWizard id="CreateUserWizard1" OnCreatedUser="CreateUserWizard1_CreatedUser" Runat="server" > <WizardSteps> <asp:WizardStep> <asp:Label id="lblFirstName" Text="First Name:" AssociatedControlID="txtFirstName" Runat="server" /> <br /> <asp:TextBox id="txtFirstName" Runat="server" /> <br /><br /> <asp:Label id="lblLastName" Text="Last Name:" AssociatedControlID="txtLastName" Runat="server" /> <br /> <asp:TextBox id="txtLastName" Runat="server" /> </asp:WizardStep> <asp:CreateUserWizardStep /> </WizardSteps> </asp:CreateUserWizard> </div> </form> </body> </html>
The page in Listing 20.27 includes a CreatedUser
event handler that executes after the new user is created. This handler adds the new user’s first and last name to a database named UserProfilesDB
.
The LoginStatus
control displays either a Login link or a Logout link, depending on your authentication status. When you click the Login link, you are transferred to the Login.aspx
page. When you click the Logout link, you are logged out of the website.
The page in Listing 20.28 contains a LoginStatus
control (see Figure 20.11).
Example 20.28. ShowLoginStatus.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Show LoginStatus</title> </head> <body> <form id="form1" runat="server"> <div> <asp:LoginStatus id="LoginStatus1" Runat="server" /> <hr /> Additional information is available to registered users. Log in to view the additional information. </div> </form> </body> </html>
After you open the page in Listing 20.28, if you click the Login link, you are redirected to the Login page. If you enter a valid username and password, you are redirected back to the ShowLoginStatus.aspx
page.
The LoginStatus
control supports the following properties:
LoginImageUrl
—. Enables you to specify an image for the Login link.
LoginText
—. Enables you to specify the text for the Login link.
LogoutAction
—. Enables you to control what happens when the Logout link is clicked. Possible values are Redirect
, RedirectToLoginPage
, and Refresh
.
LogoutImageUrl
—. Enables you to specify an image for the Logout link.
LogoutPageUrl
—. Enables you to specify a page to which the user is redirected when the user logs out. This property is ignored unless the LogoutAction
property is set to the value Redirect
.
LogoutText
—. Enables you to specify the text for the Logout link.
The LoginStatus
control also supports the following two events:
LoggingOut
—. Raised before the user is logged out.
LoggedOut
—. Raised after the user is logged out.
The LoginName
control displays the current user’s registered username. If the current user is not authenticated, the LoginName
control renders nothing.
The page in Listing 20.28 contains both a LoginName
and LoginStatus
control.
Example 20.28. ShowLoginName.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Show LoginName</title> </head> <body> <form id="form1" runat="server"> <div> <asp:LoginName id="LoginName1" FormatString="{0} /" Runat="server" /> <asp:LoginStatus id="LoginStatus1" Runat="server" /> <hr /> Additional information is available to registered users. Log in to view the additional information. </div> </form> </body> </html>
When you first open the page in Listing 20.28, the LoginName
control displays nothing. However, if you login by clicking the Login link, then the LoginName
control displays your username (see Figure 20.12).
The LoginName
control supports the following property:
FormatString
—. Enables you to format the user name when the user name is rendered
The ChangePassword
control enables a user (or administrator) to change a user password. The page in Listing 20.29 illustrates how you can use this control.
Example 20.29. ShowChangePassword.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <style type="text/css"> .changePassword { font:14px Verdana,Sans-Serif; background-color:lightblue; border:solid 3px black; padding:4px; } .changePassword_title { background-color:darkblue; color:white; font-weight:bold; } .changePassword_instructions { font-size:12px; text-align:left; padding:10px; } .changePassword_button { border:solid 1px black; padding:3px; } </style> <title>Show ChangePassword</title> </head> <body> <form id="form1" runat="server"> <div> <asp:LoginName ID="LoginName1" runat="server" /> <asp:ChangePassword id="ChangePassword1" InstructionText="Complete this form to create a new password." DisplayUserName="true" ContinueDestinationPageUrl="~/Default.aspx" CancelDestinationPageUrl="~/Default.aspx" CssClass="changePassword" TitleTextStyle-CssClass="changePassword_title" InstructionTextStyle-CssClass="changePassword_instructions" ChangePasswordButtonStyle-CssClass="changePassword_button" CancelButtonStyle-CssClass="changePassword_button" ContinueButtonStyle-CssClass="changePassword_button" Runat="server" /> </div> </form> </body> </html>
The form in Listing 20.29 includes form fields for entering your username, old password, and new password (see Figure 20.13). After you submit the form, your old password is changed to the new password.
Notice that the ChangePassword
control in Listing 20.29 includes a DisplayUserName
property. When this property is enabled, the username form field is rendered. You don’t need to include the DisplayUserName
property when you place the page within a password-protected section of your web application. In that case, the ChangePassword
control uses the name of the current user automatically.
After the user changes his password, you can use the ChangePassword
control to automatically send an email message that contains the new password. The page in Listing 20.30 contains a ChangePassword
control that automatically sends an email.
You can send a user’s password in an email message even when password is encrypted or hashed by the membership provider.
Example 20.30. ChangePasswordEmail.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>ChangePassword Email</title> </head> <body> <form id="form1" runat="server"> <div> <asp:ChangePassword id="ChangePassword1" DisplayUserName="true" Runat="server"> <MailDefinition From="[email protected]" BodyFileName="ChangePassword.txt" Subject="Your New Password" /> </asp:ChangePassword> </div> </form> </body> </html>
Notice that the ChangePassword
control in Listing 20.30 includes a MailDefinition
property that defines the email sent by the control. The ChangePassword
control emails the message contained in Listing 20.31.
The email message in Listing 20.31 includes two special expressions: <% UserName %>
and <% Password %>
. When the email is sent, the user’s existing username and new password are substituted for these expressions.
The MailDefinition
class uses the email server configured by the smtp
element in the web configuration file. For more information on configuring the smtp
element, see the earlier section of this chapter, “Sending a Create User Email Message.”
If you need to completely modify the appearance of the ChangePassword
control, then you can use templates to format the control. The ChangePassword
control supports both a ChangePasswordTemplate
and a SuccessTemplate
.
The page in Listing 20.32 illustrates how you can use both the templates supported by the ChangePassword
control (see Figure 20.14).
Example 20.32. ChangePasswordTemplate.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>ChangePassword Template</title> </head> <body> <form id="form1" runat="server"> <div> <asp:ChangePassword id="ChangePassword1" DisplayUserName="true" Runat="server"> <ChangePasswordTemplate> <h1>Change Password</h1> <asp:Label id="FailureText" EnableViewState="false" ForeColor="Red" Runat="server" /> <br /> <asp:Label id="lblUserName" Text="User Name:" AssociatedControlID="UserName" Runat="server" /> <br /> <asp:TextBox id="UserName" Runat="server" /> <br /><br /> <asp:Label id="lblCurrentPassword" Text="Current Password:" AssociatedControlID="CurrentPassword" Runat="server" /> <br /> <asp:TextBox id="CurrentPassword" TextMode="Password" Runat="server" /> <br /><br /> <asp:Label id="lblNewPassword" Text="New Password:" AssociatedControlID="NewPassword" Runat="server" /> <br /> <asp:TextBox id="NewPassword" TextMode="Password" Runat="server" /> <br /><br /> <asp:Button id="btnChangePassword" Text="Change Password" CommandName="ChangePassword" Runat="server" /> </ChangePasswordTemplate> <SuccessTemplate> Your password has been changed! </SuccessTemplate> </asp:ChangePassword> </div> </form> </body> </html>
You can use controls with the following IDs in the ChangePasswordTemplate
template:
UserName
CurrentPassword
ConfirmPassword
NewPassword
FailureText
You also can add Button
controls with the following values for the CommandName
property:
ChangePassword
Cancel
Continue
If a user forgets her password, then she can use the PasswordRecovery
control to email herself her password. The PasswordRecovery
control either sends the user’s original password or resets the password and sends the new password.
The page in Listing 20.33 contains a PasswordRecovery
control.
Example 20.33. ShowPasswordRecovery.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <style type="text/css"> .passwordRecovery { font:14px Verdana,Sans-Serif; background-color:lightblue; border:solid 3px black; padding:4px; } .passwordRecovery_title { background-color:darkblue; color:white; font-weight:bold; } .passwordRecovery_instructions { font-size:12px; text-align:left; padding:10px; } .passwordRecovery_button { border:solid 1px black; padding:3px; } </style> <title>Show PasswordRecovery</title> </head> <body> <form id="form1" runat="server"> <div> <asp:PasswordRecovery id="PasswordRecovery1" CssClass="passwordRecovery" TitleTextStyle-CssClass="passwordRecovery_title" InstructionTextStyle-CssClass="passwordRecovery_instructions" SubmitButtonStyle-CssClass="passwordRecovery_button" Runat="server"> <MailDefinition From="[email protected]" Subject="Password Reminder" /> </asp:PasswordRecovery> </div> </form> </body> </html>
After you open the page in Listing 20.33 in your web browser, you are first asked to enter your username (see Figure 20.15). Next, you are asked to enter the answer to the security question that you entered when registering. Finally, a password is emailed to your registered email account.
Before you use the PasswordRecovery
control, you must specify your mail server settings in your application’s web configuration file. See the earlier section in this chapter, “Sending a Create User Email Message.”
By default, the PasswordRecovery
control first resets your password before sending you the password. In the next section, you learn how to send a user’s original password.
By default, the PasswordRecovery
control does not send a user’s original password. If you don’t want the PasswordRecovery
control to reset a user’s password before sending it, then you must change the configuration of the membership provider. Three configuration settings matter: passwordFormat
, enablePasswordRetrieval
, and enablePasswordReset
.
By default, the passwordFormat
attribute has the value Hashed
. When passwords are hashed, the PasswordRecovery
control cannot send a user’s original password. This limitation makes sense because when passwords are hashed, the actual passwords are never stored anywhere. If you want to send a user his original password, then you need to set the passwordFormat
attribute to either the value Clear
or Encrypted
.
By default, the enablePasswordRetrieval
attribute has the value False
. Therefore, if you want to send a user his original password, you must enable this property in the web configuration file.
Finally, by default, the enablePasswordReset
attribute has the value True
. Regardless of the value of the passwordFormat
or enablePasswordRetrieval
attributes, you can always reset a user’s password and email the new password to the user.
The web configuration file in Listing 20.34 contains the necessary configuration settings to enable a user’s original password to be sent.
Example 20.34. Web.Config
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.web> <authentication mode="Forms" /> <membership defaultProvider="MyMembership"> <providers> <add name="MyMembership" type="System.Web.Security.SqlMembershipProvider" connectionStringName="LocalSqlServer" passwordFormat="Clear" enablePasswordRetrieval="true" /> </providers> </membership> </system.web> </configuration>
The configuration file in Listing 20.34 causes passwords to be stored in plain text rather than hashed. Furthermore, password retrieval is enabled.
When you use the CreateUserWizard
control to register, you are required to select a security question and answer. The PasswordRecovery
control displays a form that contains the security question. If you cannot enter the correct security answer, then your password is not sent.
If you do not want to require users to answer a security question before receiving their passwords, then you can modify the configuration of the membership provider. The web configuration file in Listing 20.35 assigns the value false
to the requiresQuestionAndAnswer
attribute.
Example 20.35. Web.Config
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.web> <authentication mode="Forms" /> <membership defaultProvider="MyMembership"> <providers> <add name="MyMembership" type="System.Web.Security.SqlMembershipProvider" connectionStringName="LocalSqlServer" requiresQuestionAndAnswer="false" /> </providers> </membership> </system.web> </configuration>
If you need to completely customize the appearance of the PasswordRecovery
control, you can use templates. The PasswordRecovery
control supports the following three types of templates:
UserNameTemplate
QuestionTemplate
SuccessTemplate
The page in Listing 20.36 illustrates how you can use all three of these templates.
Example 20.36. PasswordRecoveryTemplate.aspx
<%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <style type="text/css"> html { font:12px Arial,Sans-Serif; } h1 { font:bold 16px Arial,Sans-Serif; color:DarkGray; } </style> <title>PasswordRecovery Template</title> </head> <body> <form id="form1" runat="server"> <div> <asp:PasswordRecovery id="PasswordRecovery1" Runat="server"> <MailDefinition From="[email protected]" Subject="Password Reminder" BodyFileName="PasswordRecovery.txt" /> <UserNameTemplate> <h1>User Name</h1> <asp:Label id="FailureText" EnableViewState="false" ForeColor="Red" Runat="server" /> <br /> <asp:Label id="lblUserName" Text="Enter your user name:" AssociatedControlID="UserName" Runat="server" /> <br /> <asp:TextBox id="UserName" Runat="server" /> <br /> <asp:Button id="btnSubmit" Text="Next" CommandName="Submit" Runat="server" /> </UserNameTemplate> <QuestionTemplate> <h1>Security Question</h1> <asp:Label id="FailureText" EnableViewState="false" ForeColor="Red" Runat="server" /> <br /> <asp:Label id="Question" Text="Enter your user name:" AssociatedControlID="Answer" Runat="server" /> <br /> <asp:TextBox id="Answer" Runat="server" /> <br /> <asp:Button id="btnSubmit" Text="Next" CommandName="Submit" Runat="server" /> </QuestionTemplate> <SuccessTemplate> <h1>Success</h1> An email has been sent to your registered email account that contains your user name and password. </SuccessTemplate> </asp:PasswordRecovery> </div> </form> </body> </html>
The UserNameTemplate
must contain a control with an ID of UserName
. You also can include a control with an ID of FailureText
when you want to display error messages. This template also must contain a Button
control with a CommandName
that has the value Submit
.
The QuestionTemplate
must contain a control with an ID of Question
and a control with an ID of Answer
. Optionally, you can include a FailureText
control when you want to display error messages. It also must have a Button
control with a CommandName
that has the value Submit
.
The SuccessTemplate
, on the other hand, does not require any special controls.
Notice that the PasswordRecovery
control in Listing 20.36 includes a MailDefinition
property that references a custom email message. The message is contained in Listing 20.37.
The email message in Listing 20.37 contains substitution expressions for both the username and password.
The LoginView
control enables you to display different content to different users depending on their authentication status. For example, the page in Listing 20.38 displays different content for authenticated users and anonymous users (see Figure 20.16).
Example 20.38. ShowLoginView.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Show LoginView</title> </head> <body> <form id="form1" runat="server"> <div> <asp:LoginStatus id="LoginStatus" Runat="server" /> <hr /> <asp:LoginView id="LoginView1" Runat="server"> <AnonymousTemplate> This content is displayed to anonymous users. </AnonymousTemplate> <LoggedInTemplate> This content is displayed to authenticated users. </LoggedInTemplate> </asp:LoginView> </div> </form> </body> </html>
The LoginView
control in Listing 20.38 contains two templates: an AnonymousTemplate
and a LoggedInTemplate
. Only one of the two templates is displayed at a time.
The page also includes a LoginStatus
control. You can use this control to log in and log out quickly.
You also can use the LoginView
control to display different content to users who belong to different roles. The page in Listing 20.39 contains a LoginView
that contains two RoleGroup
controls. The first RoleGroup
contains content that is displayed to members of the Administrator role. The second RoleGroup
contains content that is displayed to members of the Manager and Worker roles.
Example 20.39. LoginViewRoles.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Dim status As MembershipCreateStatus ' Create Bill Membership.CreateUser("Bill", "secret_", "[email protected]", "dog", "rover", True, status) ' Create Ted Membership.CreateUser("Ted", "secret_", "[email protected]", "dog", "rover", True, status) ' Create Fred Membership.CreateUser("Fred", "secret_", "[email protected]", "dog", "rover", True, status) ' Create Administrator Role If Not Roles.RoleExists("Administrator") Then Roles.CreateRole("Administrator") Roles.AddUserToRole("Bill", "Administrator") End If ' Create Manager Role If Not Roles.RoleExists("Manager") Then Roles.CreateRole("Manager") Roles.AddUserToRole("Bill", "Manager") Roles.AddUserToRole("Ted", "Manager") End If ' Create Worker Role If Not Roles.RoleExists("Worker") Then Roles.CreateRole("Worker") Roles.AddUserToRole("Fred", "Worker") End If End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>LoginView Roles</title> </head> <body> <form id="form1" runat="server"> <div> <asp:LoginStatus id="LoginStatus" Runat="server" /> <hr /> <asp:LoginView id="LoginView1" Runat="server"> <RoleGroups> <asp:RoleGroup Roles="Administrator"> <ContentTemplate> This content is displayed to Administrators. </ContentTemplate> </asp:RoleGroup> <asp:RoleGroup Roles="Manager,Worker"> <ContentTemplate> This content is displayed to Managers and Workers. </ContentTemplate> </asp:RoleGroup> </RoleGroups> </asp:LoginView> </div> </form> </body> </html>
The Page_Load()
handler in Listing 20.39 creates three users named Bill, Ted, and Fred. Bill is added to both the Administrator and Manager roles, Ted is added to the Manager role, and Fred is added to the Worker role.
The content of only one RoleGroup
is displayed by the LoginView
control at a time. If a user matches more than one RoleGroup
, then the content of the first RoleGroup
matched is displayed and the other RoleGroups
are ignored.
Before you can use the page in Listing 20.39, you must enable roles in the web configuration file. The file in Listing 20.40 contains the necessary roleManager
element.
This chapter was devoted to the ASP.NET Login
controls. In the first section, you were provided with an overview of the Login
controls. You learned how to create both a Login and Registration page.
Next, we examined each of the Login
controls one by one. You learned how to use the Login
control to authenticate users and the CreateUserWizard
control to register new users. You also learned how to send an email to new users automatically.
We also examined the LoginStatus
and LoginView
controls. You learned how to display either a Login or Logout link with the LoginStatus
control. You learned how to display the current user’s name with the LoginName
control.
You also learned how to change passwords and send password reminders by using the ChangePassword
and PasswordRecovery
controls. You learned how to customize both of these controls by using templates.
Finally, you learned how to use the LoginView
control to display different content to different users, depending on their authentication status. We also discussed how you can use roles with the LoginView
control.