Description: The Login page authenticates a customer's username and password credentials against a database. Users can log in at any time by clicking the "Sign In" button in the header (_Header.ascx), but login is not required in order to view Adventure Works Cycles items or add them to a shopping cart. If users are not logged in, the shopping cart is created using a temporary user ID.
Users must be logged in to perform certain restricted tasks in the application. For example, if a user wants to check out but has not already logged in, the checkout page (Checkout.aspx) displays the login page and asks the user to enter a user name and password.
After the user has logged in, the checkout page migrates items from the temporary shopping cart to the user's permanent account. The login page then redirects back to the originating page.
Forms-Based Security Notes: The Login.aspx page provides customers with a forms-based login page through which they can authenticate themselves in the Adventure Works Cycles application. Adventure Works Cycles authentication uses ASP.NET forms-based authentication. When a user has been authenticated, a cookie is created that maintains the authentication information for the current user for the current session.
Forms-based authentication is enabled by making a <security> entry in the application's Web.config file that looks like this:
<system.web>
<authentication mode="Forms">
<forms name="AdventureWorksStoreAuth"
loginUrl="login.aspx" protection="All" path="/"></forms>
</authentication>
</system.web>
The loginurl attribute specifies the login page that the application should redirect to any time a user attempts to access an application resource that does not allow anonymous access.
For example, within the Adventure Works Cycles application we have configured three pages -- account order history (OrderList.aspx), account order details (OrderDetails.aspx), and order checkout (CheckOut.aspx) -- to explicitly require authenticated user access. To create these restrictions, we made an entry for each restricted page in the Web.config, as shown below (the "?" user stands for "anonymous" -- non-authenticated -- users):
<location path="OrderList.aspx">
<system.web>
<authorization>
<deny users="?"/>
</authorization>
</system.web>
</location>
<location path="OrderDetails.aspx">
<system.web>
<authorization>
<deny users="?"/>
</authorization>
</system.web>
</location>
<location path="CheckOut.aspx">
<system.web>
<authorization>
<deny users="?"/>
</authorization>
</system.web>
</location>
When a user attempts to access any of these pages, the ASP.NET forms-based security system will automatically redirect them to the Login.aspx page, and will continue to prevent them from accessing those restricted pages until they have successfully validated their user name and password credentials to the Adventure Works Cycles application.
An important feature of this type of authentication is that the mechanism is entirely up to you. You (not ASP.NET) determine exactly what the login page looks like. For example, the login page in the Adventure Works Cycles has been created to have the same look and feel as the rest of the application. As the application developer, you (not ASP.NET) can also decide what credential store the supplied username and password should be verified against. In the Adventure Works Cycles example, we keep the user name and password in our CustomersDB table.
Advantages of Forms-Based Authentication: The ASP.NET authentication mechanism used here is preferable to the HTTP Basic/Digest Authentication solutions supported by IIS and ASP today because it enables developers to:
Note : Basic/Digest authentication is still fully supported by ASP.NET. The forms-based authentication solution used by Adventure Works Cycles, as well as Passport authentication support, are simply additional authentication options now built into ASP.NET.
Implementation Notes: The Login page logic is encapsulated entirely within its LoginButton_Click event handler. This event handler is called on the server when a user clicks the "Sign In Now" ImageButton on the client.
The LoginButton_Click event handler attempts to authenticate a client user using the values entered within the Email and Password textbox server controls. This authentication check is done using the Login() method of the CustomersDB class. This method internally uses the usp_CustomerLogin and usp_CustomerDetail stored procedures to retrieve customer information stored in the Adventure Works Cycles database. The method then compares a one-way hash of the typed password plus password salt for the user specified, and if they match the login succeeds. See the document Building Secure ASP.NET Applications for more details about password salting and hashing.
If the login was successful (i.e., the email and password values match those stored in the database), the LoginButton_Click event handler performs three important actions:
If the login was unsuccessful (ie: either the email name was unknown or the hash of the salted password did not match the one stored in the Adventure Works Cycles customers database), the LoginButton_Click event handler will customize the page with a "Login Failed" error message and redisplay the page.
Validating User Input: The page requires that users enter a name and email address. If you look at the source for the LoginButton_Click event handler, you'll see that there is no input validation code. Instead, we use the built-in ASP.NET validation controls, which enable you to declaratively specify validation constraints on any input control.
ASP.NET comes with built-in validation controls to handle almost any validation requirement: the RequiredField, CompareValidator, RegularExpressionValidator, RangeValidator, and CustomValidator controls. The validation control architecture is extensible, so that other situation-specific controls (ZIP code validators, country code validators, etc) can also be developed by third parties.
You can put a validation control anywhere on a page and declaratively link it to a target input control using the validator's ControlToValidate property. You can optionally specify a Text property that displays in place of the validation control if the input data fails the validation test. If necessary, you can use multiple validators to chain validation logic for a single control (for example, a field is required and must meet a specified pattern).
If the page is displayed in a browser that supports EcmaScript 1.2 and the Dynamic HTML (DHTML) 4.0, the validation controls can perform client-side validation, which provides immediate feedback to the user. The validators also perform their check in server code, so if the browser does not support DHMTL, or if client-side scripting is disabled, the validation check is still performed. No code changes are required to enable either scenario -- all logic required to handle the checks on both basic and DHTML-compatible browsers is built into the controls themselves.
If you are using validation controls, your server code can determine whether the user's input passed the check by testing the IsValid property of the validation control. Additionally, you can check the page's IsValid property; this property is an aggregate of the IsValid properties of all the validators on the page. If any one validation has detected a failure, the page's IsValid property is set to false.
That's how the Login page works. Only if all controls on the page are valid will we go ahead and log the customer in. If one of the input fields is invalid, then the page will simply be redisplayed again, with the validation controls automatically taking care of displaying the appropriate error message to the user.