Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Pro ASP.NET 2.0 In CSharp 2005 (2005) [eng]

.pdf
Скачиваний:
107
Добавлен:
16.08.2013
Размер:
29.8 Mб
Скачать

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.

C H A P T E R 2 1 M E M B E R S H I P

731

Table 21-9. The Events of the Login Control

Event

Description

LoggingIn

Raised before the user gets authenticated by the control.

LoggedIn

Raised after the user has been authenticated by the control.

LoginError

Raised when the login of the user failed for some reason (such as a wrong

 

password or user name).

Authenticate

Raised to authenticate the user. If you catch this event, you have to

 

authenticate the user on your own, and the Login control completely

 

relies on your authentication code.

 

 

You can catch the first three events (in the previous table) to perform some actions before the user gets authenticated, after the user has been authenticated, and if an error has happened during the authentication process. For example, you can use the LoginError event to automatically redirect the user to the password recovery page after a specific number of attempts, as follows:

protected void Page_Load(object sender, EventArgs e)

{

if (!this.IsPostBack) ViewState["LoginErrors"] = 0;

}

protected void LoginCtrl_LoginError(object sender, EventArgs e)

{

// Increase the number of invalid logins

int ErrorCount = (int)ViewState["LoginErrors"] + 1; ViewState["LoginErrors"] = ErrorCount;

// Now validate the number of errors

if ((ErrorCount > 3) && (LoginCtrl.PasswordRecoveryUrl != string.Empty)) Response.Redirect(LoginCtrl.PasswordRecoveryUrl);

}

The Login control fires the events in the order shown in Figure 21-13.

Figure 21-13. The order of the Login control events

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

733

{

e.Authenticated = true;

}

else

{

e.Authenticated = false;

}

}

Of course, in this case you cannot use any default Membership provider. You have to implement your own validation function that accepts these additional parameters. But the Login control forces you not to use Membership at all. The validation function can be any type of function you want. You just need to set the e.Authenticated property appropriately. Then you can use the Login control for whatever login mechanism you want.

The LoginStatus Control

The LoginStatus control is a simple control that displays either a login link if the user is not authenticated or a logout link if the user is authenticated. The login link automatically redirects to the configured login page, and the logout link automatically calls the method FormsAuthentication.SignOut for logging off the user. The control is fairly simple, and therefore customization is simple as well.

<asp:LoginStatus ID="LoginStatus1" runat="server" LoginText="Sign In"

LogoutText="Sign Out" LogoutPageUrl="~/Default.aspx" LogoutAction="Redirect" />

The LoginStatus control offers a couple of properties for customizing the text shown for the links and the URLs to redirect to when the user clicks the link. You can find the most important properties in Table 21-10.

Table 21-10. Properties for Customizing the LoginStatus Control

Property

Description

LoginText

The text displayed if the user is not signed in.

LoginImageUrl

A URL for an image displayed as an icon for the login link.

LogoutText

The text displayed if the user is authenticated.

LogoutImageUrl

A URL for an image displayed as icon for the logout link.

LogoutAction

Configures the action the control performs if the user clicks the logout link

 

that is displayed when the user is authenticated. Valid options are Refresh,

 

Redirect, and RedirectToLoginPage. The first option just refreshes the

 

current page, the second option redirects to the page configured in the

 

LogoutPageUrl, and the last option redirects to the login page.

LogoutPageUrl

A page to redirect to if the user clicks the logout link and the LogoutAction is

 

set to Redirect.

 

 

The LoginView Control

This control is fairly simple but extremely powerful. It allows you to display a different set of controls for anonymous and authenticated users. Further, it even allows you display different content

734C H A P T E R 2 1 M E M B E R S H I P

based on which roles the currently logged-in user is assign to. But you will learn more about roles and their connection to the LoginView control in Chapter 23. For now you will learn how to display different content for anonymous users and for authenticated users.

The LoginView control is a template control with different types of templates—one for anonymous users, one for authenticated users, and one for supporting role-based templates. Within those templates, you just add the controls to display for the corresponding situation as follows (rolebased templates are encapsulated into RoleGroup controls, but you will learn more about them in Chapter 23):

<asp:LoginView ID="LoginViewCtrl" runat="server">

<AnonymousTemplate>

<h2>You are anonymous</h2>

</AnonymousTemplate>

<LoggedInTemplate>

<h2>You are logged in</h2>

Submit your comment: <asp:TextBox runat="server" ID="CommentText" /> <br />

<asp:Button runat="server" ID="SubmitCommentAction" Text="Submit" />

</LoggedInTemplate>

</asp:LoginView>

The previous control displays some simple text for anonymous users and some text in a text box together with a button for logged-in users, as shown in Figure 21-14. Furthermore, the control supports two events you can catch for initializing content controls of different templates appropriately before they are displayed:

ViewChanging, which is raised before the control displays content defined in another template

ViewChanged, which is raised after the control has changed the content display from one template to another

Figure 21-14. The LoginView control for anonymous and authenticated users

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>