Login.aspx File
Logon.aspx is the file to which the request is redirected if ASP.NET does not find a cookie with the request. This URL was set up in the configuration file. In the following example, a form containing two text boxes (labeled E-mail Name and Password) and a Submit button is presented to the client user. The user enters the e-mail name and password, and clicks the Submit button. The code then looks for this name and password combination in an XML file located in this directory. If it is in the file, the user is connected to Default.aspx. If it is not, the AddUser.aspx file is called.
To create a file to log on a user
Import the necessary namespaces.
<%@ Page LANGUAGE="C#" %> <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.SqlClient" %> <%@ Import Namespace="System.Web.Security " %> <%@ Import Namespace="System.IO" %> <html> <head> <title>Forms Authentication</title>
Create a script section for the code.
<script runat=server>
Implement a Logon_Click function.
private void Logon_Click(Object sender, EventArgs e) {
If the page is not valid, tell the user.
if( !Page.IsValid ) { Msg.Text = "Some required fields are invalid."; return; }
Set up a string named
cmd
that is initialized to UserEmail="MyName", where MyName is the user's e-mail name. The regular expression validator control attached to the input control has already determined that the e-mail name is formatted properly and does not contain invalid characters.String cmd = "UserEmail='" + UserEmail.Value + "'";
Create a new instance of the DataSet class.
DataSet ds = new DataSet();
Read in the XML file containing authenticated user name and password combinations. The retrieved data resides in
ds
, the DataSet created in the previous step.CAUTION For the sake of simplicity and the clarity of the example, the following code does not follow best design practices for security. It does not invoke any file-locking or file-sharing flags. Also, in a commercial Web site, you should use a relational database or other secure and scalable mechanism to store the list of authenticated users.
FileStream fs = new FileStream(Server.MapPath("Users.xml"), FileMode.Open,FileAccess.Read); StreamReader reader = new StreamReader(fs); ds.ReadXml(reader); fs.Close();
Create a new instance of a DataTable named
users
that is initialized tods
.DataTable users = ds.Tables[0];
Check for any matches between the logon name and the list of names in Users.aspx. For each match found, record the name in a DataRow named
matches
.Note For the sake of simplicity, this example expects each name to be unique; therefore, only the first match found is used.
DataRow[] matches = users.Select(cmd);
Check each of the name matches found in the previous step to see whether there is a matching password for any of them.
if( matches != null && matches.Length > 0 ) {
If a user name match is found, hash the user's password and compare it to the hash stored in the Users.xml file.
DataRow row = matches[0]; string hashedpwd = FormsAuthentication.HashPasswordForStoringInConfigFile (UserPass.Value, "SHA1"); String pass = (String)row["UserPassword"]; if( 0 != String.Compare(pass, hashedpwd, false) ) // Tell the user if no password match is found. It is good // security practice give no hints about what parts of the // logon credentials are invalid. Msg.Text = "Invalid Credentials: Please try again."; else // If a password match is found, redirect the request // to the originally requested resource (Default.aspx). FormsAuthentication.RedirectFromLoginPage (UserEmail.Value, Persist.Checked); } else { // If no name matches were found, redirect the request to the // AddUser page using a Response.Redirect command. Response.Redirect("AddUser/AddUser.aspx"); } } </script> <body>
Display a form to collect the logon information.
<form runat=server> <span style="background:#80FF80"> <h3><font face="Verdana">Logon Page</font></h3></span> <table> <tr>
Create a User E-mail Name text box. Add a RequiredFieldValidator control and a RegularExpressionValidator control that check for a valid e-mail name entry. The RegularExpressionValidator verifies that the e-mail address is in valid e-mail format (for example, name@contoso.com) and does not contain invalid characters that could compromise security.
<td>e-mail:</td> <td><input id="UserEmail" type="text" runat=server/></td> <td><ASP:RequiredFieldValidator ControlToValidate="UserEmail" Display="Static" ErrorMessage="*" runat="server"/> </td> <td><asp:RegularExpressionValidator id="RegexValidator" ControlToValidate="UserEmail" ValidationExpression="^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$" EnableClientScript="false" Display="Static" ErrorMessage="Invalid format for e-mail address." runat="server"/> </td> </tr> <tr>
Create a Password text box.
<td>Password:</td> <td><input id="UserPass" type=password runat=server/></td> <td><ASP:RequiredFieldValidator ControlToValidate="UserPass" Display="Static" ErrorMessage="*" runat="server"/> </td> </tr> <tr>
Create a Persistent Cookie check box. If the Persistent Cookie box is selected, the cookie is valid across browser sessions. Otherwise, when the browser is closed, the cookie is destroyed. Issuing persistent cookies might be desirable for some sites for reasons of convenience, but it is offers less protection than issuing short-lived cookies.
<td>Persistent Cookies:</td> <td><ASP:CheckBox id=Persist runat="server" autopostback="true"/> </td> <td></td> </tr> </table>
Create a Submit button that causes the Logon_Click event to be raised on postback.
<input type="submit" OnServerClick="Logon_Click" Value="Logon" runat="server"/><p> <asp:Label id="Msg" ForeColor="red" Font-Name="Verdana" Font-Size="10" runat="server"/> </form> </body> </html>
See Also
ASP.NET Web Application Security | Forms Authentication Using an XML Users File