Pro ASP.NET 2.0 In CSharp 2005 (2005) [eng]
.pdf
728 C H A P T E R 2 1 ■ M E M B E R S H I P
Table 21-7. Continued
Property |
Description |
LoginButtonImageUrl |
If you display the login button as an image, you have to |
|
provide a URL to an image that is displayed for the button. |
DestinationPageUrl |
If the login attempt was successful, the Login control |
|
redirects the user to this page. This property is empty |
|
by default. If empty, it uses the forms authentication |
|
infrastructure for redirecting either to the originally |
|
requested page or to the defautlUrl configured in |
|
web.config for forms authentication. |
DisplayRememberMe |
Enables you to show and hide the Remember Me check |
|
box. By default this property is set to true. |
FailureAction |
Defines the action the control performs after a login |
|
attempt failed. The two valid options are Refresh and |
|
RedirectToLoginPage. The first one refreshes just the |
|
current page, and the second one redirects to the config- |
|
ured login page. Of course, the second one is useful if you |
|
use the control anywhere else instead of the login page. |
RememberMeSet |
Defines the default value for the Remember Me check box. |
|
By default this option is set to false, which means the check |
|
box is not checked by default. |
VisibleWhenLoggedIn |
If set to false, the control automatically hides itself if the |
|
user is already logged in. If set to true (default), the Login |
|
control is displayed even if the user is already logged in. |
CreateUserUrl |
Defines a hyperlink to a page in the website that allows you |
|
to create (register!) a user. Therefore, this is typically used |
|
for enabling the user to access a registration page. Typically |
|
this page displays the CreateUserWizard control. |
CreateUserText |
Defines the text displayed for the CreateUserUrl hyperlink. |
CreateUserIconUrl |
Defines a URL to an image displayed together with the text |
|
for the CreateUserUrl hyperlink. |
HelpPageUrl |
URL for redirecting the user to a help page. |
HelpPageText |
Text displayed for the hyperlink configured in the |
|
HelpPageUrl property. |
HelpPageIconUrl |
URL to an icon displayed together with the text for the |
|
HelpPageUrl hyperlink. |
PasswordRecoveryUrl |
URL for redirecting the user to a password recovery page. |
|
This page is used if the user has forgotten the password. |
|
Typically this page displays the PasswordRecovery control. |
PasswordRecoveryText |
The text displayed for the hyperlink configured in |
|
PasswordRecoveryUrl. |
PasswordRecoveryIconUrl |
Icon displayed together with the text for the |
|
PasswordRecoveryUrl. |
|
|
Templates and the Login Control
As you can see, the control is nearly completely customizable through these properties. But as you probably have seen, you cannot define any validation expressions for validating the input. Of course, you can do validation on the server side within the event procedures offered by the Login control. However, generally, if you want to add any controls to the Login control, you can’t do that
C H A P T E R 2 1 ■ M E M B E R S H I P |
729 |
through the properties introduced previously. For example, what if you have an additional text box for strong authentication with a second password or user access key as on some governmental pages?
Fortunately, the Login control supports templates just as other controls such as the GridView control do. With templates, you can customize the contents of the Login control without any limitations. You can add any controls you want to your Login control. You can use a custom template for the Login control through the LayoutTemplate tag as follows:
<asp:Login ID="LoginCtrl" runat="server" BackColor="aliceblue" BorderColor="Black" BorderStyle="double">
<LayoutTemplate>
<h4>Log-In to the System</h4> <table>
<tr>
<td>
User Name: </td> <td>
<asp:TextBox ID="UserName" runat="server" /> <asp:RequiredFieldValidator ID="UserNameRequired"
runat="server"
ControlToValidate="UserName" ErrorMessage="*" />
<asp:RegularExpressionValidator ID="UsernameValidator" runat="server" ControlToValidate="UserName" ValidationExpression="[\w| ]*" ErrorMessage="Invalid User Name" />
</td>
</tr>
<tr>
<td>
Password:
</td>
<td>
<asp:TextBox ID="Password" runat="server" TextMode="Password" /> <asp:RequiredFieldValidator ID="PasswordRequired"
runat="server"
ControlToValidate="Password" ErrorMessage="*" />
<asp:RegularExpressionValidator ID="RegularExpressionValidator1" runat="server"
ControlToValidate="Password" ValidationExpression='[\w| !"§$%&/()=\-?\*]*' ErrorMessage="Invalid Password" />
</td>
</tr>
</table>
<asp:CheckBox ID="RememberMe" runat="server" Text="Remember Me" /> <asp:Literal ID="FailureText" runat="server" /><br />
<asp:Button ID="Login" CommandName="Login" runat="server" Text="Login" />
</LayoutTemplate>
</asp:Login>
730 C H A P T E R 2 1 ■ M E M B E R S H I P
With the right controls and the correct ID values for these controls in place, you don’t need to write any code for handling events. The code just works as usual except that you define the set of controls and the layout of these controls. Actually, the Login control requires at least two text boxes with the IDs UserName and Password. If those two text boxes are missing (or don’t have these ID values), the control throws an exception. All the other controls are optional, but if you specify corresponding ID values (such as Login for the login button), the Login control automatically handles their events and behaves as when you used the predefined layouts for the control. Table 21-8 lists the special ID values, their required control types, and whether they are required or optional.
Table 21-8. Special Controls for the Login Template
Control ID |
Control Type |
Required? |
UserName |
System.Web.UI.WebControls.Textbox |
Yes |
Password |
System.Web.UI.WebControls.Textbox |
Yes |
RememberMe |
System.Web.UI.WebControls.CheckBox |
No |
FailureText |
System.Web.UI.WebControls.Literal |
No |
Login |
Any control that supports event bubbling |
No |
|
and a CommandName |
|
|
|
|
The control with the ID Login can be any control that supports event bubbling and a CommandName property. It is important that you set the CommandName property to Login, because otherwise it will not be recognized in the event-handling process by the Login control. You can also add controls with other IDs that are not related to the Login control at all. The previous code includes RequiredFieldValidator and RegularExpressionValidator controls for validating the user name and password fields appropriately. If you don’t add a control with the CommandName set to Login, you have to handle the event of the control yourself and write the appropriate code for validating the user name and password and for redirecting to the originally requested page.
When using the LayoutTemplate, many of the properties originally offered by the control are not available anymore. Only the following properties are available when using the template:
•DestinationPageUrl
•VisibleWhenLoggedIn
•FailureAction
•MembershipProvider
•Password
•Username
•RememberMeSet
All the style properties and several properties for configuring text contents of default controls are not available anymore, because you can add them manually as separate controls or static text to the template for the Login control.
Programming the Login Control
The Login control supports a couple of events and properties that you can use to customize the behavior of the control. This gives you complete control over customizing the Login control (used along with the other customization possibilities such as templates or custom style properties). The Login control supports the events listed in Table 21-9.
732 C H A P T E R 2 1 ■ M E M B E R S H I P
As mentioned previously, if you catch the event, you have to add your own code for validating the user name and password. The Authenticate property supports an instance of AuthenticateEventArgs to the parameter list. This event argument class supports one property called Authenticated. If you set this property to true, the Login control assumes that authentication
was successful and raises the LoggedIn event. If set to false, it displays the FailureText and raises the LoginError event.
protected void LoginCtrl_Authenticate(object sender, AuthenticateEventArgs e)
{
if (YourValidationFunction(LoginCtrl.UserName, LoginCtrl.Password))
{
e.Authenticated = true;
}
else
{
e.Authenticated = false;
}
}
As you can see, you have direct access to the entered values through the UserName and Password properties that contain the text entered in the corresponding text boxes. If you are using template controls and require the value of another control in addition to the controls with the IDs UserName and Password, you can use the control’s FindControl method to get the control. This method requires the ID of the control and returns an instance of System.Web.UI.Control. You then just cast the control to the appropriate type and read the values you require for your custom credential validation method. The following Login control uses a template with an additional control that you will use later in the Authenticate event in your code:
<asp:Login ID="OtherLoginCtrl" runat="server" BackColor="aliceblue" BorderColor="Black" BorderStyle="double" PasswordRecoveryUrl="~/pwdrecover.aspx"
OnAuthenticate="OtherLoginCtrl_Authenticate">
<LayoutTemplate>
<font face="Courier New">
Userskey: <asp:Textbox ID="AccessKey" runat="server" /><br />
User Name: <asp:TextBox ID="UserName" runat="server" /><br /> Password: <asp:TextBox ID="Password" runat="server"
TextMode="password" Width="149px" /><br /> <asp:Button runat="server" ID="Login"
CommandName="Login" Text="Login" />
</font>
</LayoutTemplate>
</asp:Login>
In the previous code example, the user’s key is an additional value that must be provided by the user for successfully logging in. To include this value into your credential validation process, you have to modify the contents of the Authenticate event as follows:
protected void OtherLoginCtrl_Authenticate(object sender, AuthenticateEventArgs e)
{
TextBox AccessKeyText = (TextBox)OtherLoginCtrl.FindControl("AccessKey");
if (YourValidation(AccessKeyText.Text,
OtherLoginCtrl.UserName, OtherLoginCtrl.Password))
C H A P T E R 2 1 ■ M E M B E R S H I P |
735 |
The PasswordRecovery Control
The PasswordRecovery control is useful if a user has forgotten his password. This queries the user name from the user and afterward automatically displays the password question stored for the user in the credential store. If the user enters the correct answer for the password question, the password is mailed automatically to the e-mail address configured for the user. Figure 21-15 shows the PasswordRecovery control in action.
Figure 21-15. The PasswordRecovery control in action
The control includes three customizable view modes. First, the user has to enter his user name. When the user clicks the submit button, the control queries the password question through the Membership API from the underlying credential store. Second, this question is then displayed, and the user is requested to enter the correct answer. When the user enters the correct answer, an automatically generated password or the stored password is sent to the user’s e-mail address. This e-mail address was specified during the registration process (or when the user was created through the WAT). If sent successfully, the control displays a confirmation view. Any mail configuration takes place through the control’s properties, as follows. Of course, the password itself can be sent to the user only if it is not hashed. Therefore, the Membership provider must be configured in a way that it stores the passwords either encrypted or in clear-text format. If the Membership provider stores the password in a hashed form, it automatically generates a new, random password and sends the new password in the e-mail.
<asp:PasswordRecovery ID=" PasswordRecoveryCtrl" runat="server" BackColor="Azure"
BorderColor="Black" BorderStyle="solid"> <MailDefinition From="proaspnet2@apress.com"
Subject="Forgotten Password" Priority="high" />
<TitleTextStyle Font-Bold="true" Font-Italic="true" BorderStyle="dotted" />
736 C H A P T E R 2 1 ■ M E M B E R S H I P
<TextBoxStyle BackColor="Yellow" BorderStyle="double" /> <FailureTextStyle Font-Bold="true" ForeColor="Red" />
</asp:PasswordRecovery>
The control requires an e-mail SMTP server for sending the e-mail message. Therefore, you have to configure the STMP mail server in your web.config file, as follows:
<system.web>
<smtpMail serverName="MyServer" serverPort="15" from="proaspnet2@apress.com">
<fields>
<add name="smtpauthenticate" value="2"> </fields>
</smtpMail>
</system.web>
The MailDefinition allows you to set basic properties. Also, through the BodyFileName property, you can specify the name of a file containing the e-mail text. This file has to be in the same directory as the page where the control is hosted. If the control is hosted within another user control, the file has to be in the directory of the user control’s host page. The PasswordRecovery control supports different style properties for specifying formatting and layout options for the different parts of the control (just as the Login control does). For a complete list of the supported properties, refer to the MSDN documentation; these properties are similar to the properties introduced with the Login control. The control raises several different events during the password recovery process. You can catch these events for customizing the actions completed by the control. Table 21-11 lists these events.
Table 21-11. Events of the PasswordRecovery Control
Event |
Description |
VerifyingUser |
Raised before the control starts validating the user name entered. |
|
Validating the user name means looking for the user in the Membership |
|
store and retrieving the password question information. |
UserLookupError |
If the user name entered in the user name text box doesn’t exist in the |
|
Membership store, this event is raised before the failure text is displayed. |
VerifyingAnswer |
When the user clicks the submit button in the second step, the answer |
|
for the question is compared to the one stored in the Membership store. |
|
This event is raised before this action takes place. |
AnswerLookupError |
If the answer provided by the user is not correct, this event is raised by |
|
the control. |
SendingEmail |
This event is raised by the control after the answer submitted by the user |
|
has been identified as the correct answer and before the e-mail is sent |
|
through the mail server. |
SendMailError |
If the e-mail cannot be sent for some reason (for example, the mail server |
|
is not available), this event is raised by the control. |
|
|
You can use these events for preparing information before that information gets processed by the control. For example, if you want to convert all letters in the user name to lowercase letters before the control compares contents with the data stored in the Membership store, you can do this in the VerifyingUser event. Similarly, you can use the VerifyingAnswer for preprocessing information before it gets processed by the control. Both events get event arguments of type LoginCancelEventArgs, which contains a Cancel property. If you set this property to false, you can cancel the whole processing step.
C H A P T E R 2 1 ■ M E M B E R S H I P |
737 |
When catching the SendingEmail event, you have the chance to modify the contents of the e-mail message before the control actually sends the e-mail to the user. The passed MailMessageEventArgs contains a Message property that represents the actual e-mail message. By modifying the Message’s properties, such as the Attachments collection, you can add attachments, configure a CC address, or do anything else related to the e-mail message.
PasswordRecovery Templates
Like the Login control, the PasswordRecovery control can be customized completely if customization through the previously mentioned properties and styles is not sufficient for some reason. The control supports templates for every view:
•The UsernameTemplate contains all the controls displayed for the first step of the password recovery process when the user is required to enter the user name.
•Controls for the second step, the password question step, are placed in the QuestionTemplate.
•Finally, the control supports a SuccessTemplate that consists of the controls displayed for the confirmation displayed after the password has been sent successfully to the user.
Every template has certain required controls. For example, the UsernameTemplate requires a text box for entering the user name. The QuestionTemplate requires a text box for entering the question, and of course the SuccessTemplate requires a Literal control for displaying the final confirmation message. A template PasswordRecovery control might look like this:
<asp:PasswordRecovery ID=" PasswordTemplateCtrl" runat="server"> <MailDefinition From="pwd@apress.com"
Priority="high" Subject="Important information" />
<UserNameTemplate>
<span style="text-align: center"> <font face="Courier New">
<h2>Forgotten your Password?</h2> Please enter your user name:<br />
<asp:TextBox ID="UserName" runat="server" /> <br />
<asp:Button ID="SubmitButton" CommandName="Submit" runat="server" Text="Next" />
<br />
<span style="color: Red">
<asp:Literal ID="FailureText" runat="server" /> </span>
</font>
</span>
</UserNameTemplate>
<QuestionTemplate>
<span style="text-align: center"> <font face="Courier New">
<h2>Forgotten your Password?</h2>
Hello <asp:Literal ID="UserName" runat="server" />! <br /> Please answer your password-question:<br />
<asp:Literal ID="Question" runat="server" /><br /> <asp:TextBox ID="Answer" runat="server" /><br /> <asp:Button ID="SubmitButton" CommandName="Submit"
runat="Server" Text="Send Answer" /><br /> <asp:Literal ID="FailureText" runat="server" /> </span>
