Using Forms Authentication

only for RuBoard

Forms authentication uses an HTML form “based login interface. The user supplies her credentials, typically a username and password, via the form. The credentials are authenticated against some authority, such as a database or XML file of users. When authenticated, a cookie is issued to the client. On each subsequent request, the cookie is appended to the request header. On each request, the user is authenticated and, if she is authorized for the requested resource, the requested resource is returned to the client. Listing 15.3 shows the security section of the web.config file to enable Forms Authentication.

Listing 15.3 Enabling Forms Authentication
 01: <authentication mode="Forms"> 02:  <forms name="MyApp" loginUrl="PDDWA/C15/CSharp/login.aspx"> 03:   <credentials passwordFormat="SHA1"> 04:    <user name="WillyWonka" password="E8F97FBA9104D1EA5047948E6DFB67FACD9F5B73"/> 05:   </credentials> 06:  </forms> 07: </authentication> 08: 09: <authorization> 10:  <allow users="*" /> 11: </authorization> 

In Listing 15.3, you create the <authentication> and <authorization> sections of the web.config file, enabling Forms Authentication for the Web application by setting the <authentication> element's mode attribute to Forms (line 1). On line 2, you create the <forms> element. The loginUrl value defines a Web Form named login.aspx in the top-level directory as the form where the user can provide his credentials. The name attribute assigns MyApp as the name applied to the cookie.

Using the <credentials> element on lines 3 through 5, you specify one user for this Web application, "WillyWonka", whose password is "password". On line 3 you specify SHA1 as the passwordFormat . This means that passwords are stored in the configuration file, encrypted using SHA1 encryption. When authenticating a user from the login form, the username and password will be compared against <user> elements in the <credentials> section. The user will supply his password as regular text. The password will be automatically encrypted and compared to the value in the configuration file. On line 10, you set the allow element of the <authorization> section to allow all users access to the Web application.

Note

You can encrypt passwords using the FormsAuthentication class' HashPasswordForStoringInConfigFile() method:

 string = FormsAuthentication.HashPasswordForStoringInConfigFile("password", "SHA1") 

Specific resources such as .aspx files or subdirectories can be defined to use different authorization rules. This can be done in two ways, by using the <location> element in the web. config file, or by putting a web.config file in the subdirectory. Configuration files below the root directory cannot redefine the authentication scheme, but they can redefine the authorization rules for the directory that they are in and for all child directories. Listing 15.4 shows a <location> element that can be added to the web.config file to restrict access to a resource to authenticated users only.

Listing 15.4 Restricting Access to Specific Resources
 01: <location path="protected_page.aspx"> 02:   <system.web> 03:    <authorization> 04:     <deny users="?" /> 05:    </authorization> 06:   </system.web> 07:  </location> 

In Listing 15.4, you create a <location> element that restricts access to a Web Form ( protected_page.aspx ) to authenticated users only. The path attribute, on line 1, of the <location> element defines the relative path to the resource of which to restrict access. The <deny> element, on line 4, uses the users attribute to identify unauthenticated users.

Warning

The following listings depend on a file named protected_page.aspx . Create a file by this name and put only the text "This is a protected page." in it. This page is only for testing the Forms Authentication.


If an unauthenticated user requests protected_page.aspx , he will be redirected to the login page. The QueryString is automatically appended with the originally requested URL, like this:

 http://localhost/login.aspx? ReturnUrl= http%3a%2f%2flocalhost%2fprotected_page.aspx 

If you need to apply access restrictions to a subdirectory of the root directory, you can do it with a <location> element in the root web.config file, or you can create a limited web. config file in the subdirectory. The limited web.config file contains only an <authorization> section with <allow> and/or <deny> elements to define the access available. Listing 15.5 shows the web.config file used in the Members subdirectory of the Northwind sample application.

Listing 15.5 Using a Limited Config.Web in a Subdirectory
 01: <?xml version="1.0" encoding="utf-8" ?> 02: <configuration> 03:  <system.web> 04:   <authorization> 05:    <deny users="?" /> 06:   </authorization> 07:  </system.web> 08: </configuration> 

Listing 15.5 is a sample of the entire web.config file you would use in a subdirectory of your application. The configuration file has only an <authorization> section. By using the <deny> element on line 5, you restrict access to this subdirectory, and all its child files and directories, to authenticated users only. Any unauthenticated user requesting a resource in this subdirectory or any of its child directories will be redirected to the loginUrl specified in the root web.config file.

Note

When setting allow and deny values, you can use a comma delimited list of usernames, or a * to represent all users and a ? to represent all unauthenticated users.


Creating an Authentication Ticket Cookie

When a user is authenticated, an authentication ticket is generated, and a text-based cookie is sent to the client. To create the authentication ticket, you must handle the submission of the login form, and call to the Authenticate() method of the FormsAuthentication class. By default the Authenticate() method checks the <credentials> element of the web.config file for the username and password values submitted. If the Authenticate() method returns True , the user can be redirected to the originally requested resource using the FormsAuthentication.RedirectFromLoginPage() method. This method takes two parameters, the username and a boolean value indicating whether or not a persistent cookie should be created. When the RedirectFromLoginPage() method is called, an Authentication Ticket is created, and the SetCookie() method is called. The cookie is sent to the client using the name in the web.config file, and date and expiration values based on whether the cookie was intended to be persisted or not. Listing 15.6 shows the login page ( login.aspx ).

Listing 15.6 The Login Web Form
 [VB] 01: <script runat="server" language="VB"> 02:  Protected Sub Login_OnClick(Sender As Object, E As EventArgs) 03:   If FormsAuthentication.Authenticate(UserName.Text, Password.Text) Then 04:    FormsAuthentication.RedirectFromLoginPage(UserName.Text, PersistCookie.Checked) 05:   End If 06:  End Sub 07: 08:  Protected Sub Signout_OnClick(Sender As Object, E As EventArgs) 09:   FormsAuthentication.SignOut() 10:   HttpContext.Current.Response.Redirect("login.aspx") 11:  End Sub 12: </script> [C#] 01: <script runat="server" language="C#"> 02:  protected void Login_OnClick(Object sender, EventArgs e){ 03:   if(FormsAuthentication.Authenticate(UserName.Text, Password.Text)){ 04:    FormsAuthentication.RedirectFromLoginPage(UserName.Text, PersistCookie.Checked); 05:   } 06:  } 07: 08:  protected void Signout_OnClick(Object sender, EventArgs e){ 09:   FormsAuthentication.SignOut(); 10:   HttpContext.Current.Response.Redirect("login.aspx"); 11:  } 12: </script> [VB & C#] 13: <html> 14: <head> 15:  <title>Programming Datadriven Web Apps - Chapter 15</title> 16: </head> 17: <body> 18: <form runat="server"> 19: <H4>Account Logon</H4> 20:  <b>E-Mail:</b><br/> 21:  <asp:TextBox runat="server" ID="UserName" /><br/> 22:  <b>Password:</b><br/> 23:  <asp:TextBox runat="server" ID="Password" TextMode="Password" /><br/> 24:  <b>Remember Me</b><br/> 25:  <asp:CheckBox runat="server" ID="PersistCookie" /><br/> 26:  <asp:Button runat="server" ID="Login" 27:   Text="Login" 28:   OnClick="Login_OnClick" /> 29: 30:  <asp:Button runat="server" ID="Signout" 31:   Text="Sign-Out" 32:   OnClick="Signout_OnClick" /> 33: </form> 34: </body> 35: </html> 

In Listing 15.6, you create an event handler for a button click, Login_OnClick() . The event handler calls the Authenticate() method of the FormsAuthentication class (line 3), passing it the username and password values submitted by the user. If the Authenticate() method returns True , then the RedirectFromLoginPage() method is called (line 4), which issues a cookie to the client and redirects the client browser to the originally requested resource. If the PersistCookie CheckBox was checked, the PersistCookie.Checked value is True , and a persistent cookie is written to the client machine; otherwise a non-persistent cookie is issued.

Manually Creating a Forms Authentication Ticket

In Listing 15.6, you used the FormsAuthentication.Authenticate() method to validate a user's credentials against the <credentials> section of the web.config file. You can also validate users against an alternative data store, such as a database table. Since Forms Authentication.Authenticate() uses the <credentials> section to authenticate users, you must use an alternative validation method. After the credentials are validated , a call to FormsAuthentication.RedirectFromLoginPage() or FormsAuthentication.SetAuthCookie() will create an authentication ticket and pass a cookie to the client machine. The Redirect FromLoginPage() method will redirect the browser to the originally requested page, whereas SetAuthCookie() will create an authentication ticket and issue a cookie to the client, but will not perform a redirect.

Authenticating Users From a Database Table

You can authenticate users from credentials stored in a database table. Once the user submits their credentials, you compare it to the data in the database. If the credentials are valid, you create an authentication ticket by either calling FormsAuthentication.SetAuthCookie() or FormsAuthentication.RedirectFromLoginPage() .

In Listing 15.7 you create a login Web Form that validates the user's credentials against the Users table of the Samples database.

Warning

The following listings depend on a database named "samples". On the companion Web site (http://www.samspublishing.com) you can download the SQL Server script and text files to create this database, or an Access 2000 version of this database.


Listing 15.7 Authenticating Users From a Database Table
 [VB] 01: <%@ Import Namespace="System.Data" %> 02: <%@ Import Namespace="System.Data.SqlClient" %> 03: 04: <script runat="server" language="VB"> 05:  Protected Sub Login_OnClick(Sender As Object, E As EventArgs) 06:   Dim SqlStmt As String = "SELECT COUNT(*) FROM Users WHERE Email='" & _ 07:     UserName.Text.Trim() & "' " & _ 08:     "AND Password = '" & _ 09:     Password.Text.Trim() & "'" 10: 11:   Dim con As SqlConnection = New graphics/ccc.gif SqlConnection("server=localhost;database=samples;uid=sa;pwd=;") 12:   Dim cmd As SqlCommand = New SqlCommand(SqlStmt, con) 13:   Dim reader As SqlDataReader = Nothing 14: 15:   con.Open() 16:   reader = cmd.ExecuteReader() 17:   While reader.Read() 18:    If Int32.Parse(reader(0).ToString()) >= 1 Then 19: FormsAuthentication.RedirectFromLoginPage(UserName.Text, PersistCookie.Checked) 20:    Else 21:     ErrorMsg.Text = "<p><b><font color='#CC3300'>User not found, or bad credentials - graphics/ccc.gif try again!</b></p>" 22:    End If 23:   End While 24:  End Sub 25: 26:  Protected Sub Signout_OnClick(Sender As Object, E As EventArgs) 27:   FormsAuthentication.SignOut() 28:   HttpContext.Current.Response.Redirect("login_database.aspx") 29:  End Sub 30: </script> [C#] 01: <%@ Import Namespace="System.Data" %> 02: <%@ Import Namespace="System.Data.SqlClient" %> 03: 04: <script runat="server" language="C#"> 05:  protected void Login_OnClick(Object sender, EventArgs e){ 06:   string SqlStmt = "SELECT COUNT(*) FROM Users WHERE Email='" + 07:     UserName.Text.Trim() + "' " + 08:     "AND Password = '" + 09:     Password.Text.Trim() + "'"; 10: 11:   SqlConnection con = new graphics/ccc.gif SqlConnection("server=localhost;database=samples;uid=sa;pwd=;"); 12:   SqlCommand cmd = new SqlCommand(SqlStmt, con); 13:   SqlDataReader reader = null; 14: 15:   con.Open(); 16:   reader = cmd.ExecuteReader(); 17:   while(reader.Read()){ 18:    if(Int32.Parse(reader[0].ToString()) >= 1){ 19:     FormsAuthentication.RedirectFromLoginPage(UserName.Text, PersistCookie.Checked); 20:    } else{ 21:     ErrorMsg.Text = "<p><b><font color='#CC3300'>User not found, or bad credentials - graphics/ccc.gif try again!</b></p>"; 22:    } 23:   } 24:  } 25: 26:  protected void Signout_OnClick(Object sender, EventArgs e){ 27:   FormsAuthentication.SignOut(); 28:   HttpContext.Current.Response.Redirect("login_database.aspx"); 29:  } 30: </script> [VB & C#] 31: <html> 32: <head> 33:  <title>Programming Datadriven Web Apps - Chapter 15</title> 34: </head> 35: <body style="font:9pt Verdana, Arial, sans-serif;"> 36: <form runat="server"> 37: <H4>Account Logon Using a Database</H4> 38:  <asp:Label runat="server" id="ErrorMsg" /> 39:  <b>E-Mail:</b><br/> 40:  <asp:TextBox runat="server" ID="UserName" /><br/> 41:  <b>Password:</b><br/> 42:  <asp:TextBox runat="server" ID="Password" TextMode="Password" /><br/> 43:  <b>Remember Me</b><br/> 44:  <asp:CheckBox runat="server" ID="PersistCookie" /><br/> 45: 46:  <asp:Button runat="server" ID="Login" 47:   Text="Login" 48:   OnClick="Login_OnClick" /> 49: 50:  <asp:Button runat="server" ID="Signout" 51:   Text="Sign-Out" 52:   OnClick="Signout_OnClick" /> 53: </form> 54: </body> 55: </html> 

Note

On the companion Web site (http://www.samspublishing.com) you can download the OleDb Managed Provider version of the code in Listing 15.7.


In Listing 15.7 you create a login Web Form that authenticates users from a database table. Lines 5 “24 are the Login_OnClick() event handler. In this event handler you create Managed Connection (line 11) and Command (line12) objects, and use a DataReader (line 16) to catch the results of a SELECT COUNT(*) SQL statement. The SQL statement looks for e-mail and password values that match those entered by the user. If one or more matching fields are found (in the event of duplicate user entries), the result is one or greater, and the user is authenticated. If no matching records are found, an error message (line 21) is displayed to the user.

If the user is to be authenticated, you create an authentication ticket by calling Forms Authentication.RedirectFromLoginPage() on line 19. This method creates an authentication ticket, and a cookie. If the PersistCookie.Checked value is True , then the cookie is written to the client machine, otherwise it is persisted in memory, and is lost when the browser window is closed.

On lines 26-29 you create a SignOut_OnClick() event handler for the Sign-Out button. On line 27 you call the FormsAuthentication.SignOut() method to remove the authentication ticket, effectively un-authenticating the user. To access restricted resources the user will have to login again. On line 28 you use Response.Redirect() to redirect the browser back to a refreshed version of the login Web Form. Doing this clears out any input values, and ensures the ViewState is clear.

Authenticating Users From an XML File

In the same manner that you authenticate users from a database, you can authenticate users from an XML file. You compare the users credentials to the credentials in an XML file, and if valid, you issue an authentication ticket and cookie.

Listing 15.8 shows the Users.xml file, which is simply the same user data from the Users table in the Sample database.

Listing 15.8 The Users.xml File
 01: <?xml version="1.0"?> 02: <Users> 03:  <User> 04:   <UserID>1</UserID> 05:   <Email>doug.seven@dotnetjunkies.com</Email> 06:   <Password>password</Password> 07:   <FName>Doug</FName> 08:   <LName>Seven</LName> 09:  </User> 10:  <User> 11:   <UserID>2</UserID> 12:   <Email>billg@microsoft.com</Email> 13:   <Password>money</Password> 14:   <FName>Bill</FName> 15:   <LName>Gates</LName> 16:  </User> 17:  <User> 18:   <UserID>3</UserID> 19:   <Email>kobe@bball.com</Email> 20:   <Password>slamdunk</Password> 21:   <FName>Kobe</FName> 22:   <LName>Bryant</LName> 23:  </User> 24: </Users> 

Listing 15.8 is simply an XML file of usernames, passwords, first names, and last names .

In Listing 15.9 you create a login Web Form that authenticates user credentials against the Users.xml file. Listing 15.9 uses the same HTML as Listing 15.7, so I have not duplicated it here.

Listing 15.9 Authenticating Users From an XML File
 [VB] 01: <%@ Import Namespace="System.Data" %> 02: 03: <script runat="server" language="VB"> 04:  Protected Sub Login_OnClick(Sender As Object, E As EventArgs) 05:   Dim ds As New DataSet 06:   ds.ReadXml(Server.MapPath("Users.xml")) 07: 08:   Dim i As Integer 09:   For i = 0 to ds.Tables("User").Rows.Count - 1 10:    If (ds.Tables("User").Rows(i)("Email").ToString()= UserName.Text.Trim() AND graphics/ccc.gif ds.Tables("User").Rows(i)("Password").ToString() = Password.Text.Trim()) Then 11: FormsAuthentication.RedirectFromLoginPage(UserName.Text, PersistCookie.Checked) 12:    End If 13:   Next i 14: 15:   ErrorMsg.Text = "<p><b><font color='#CC3300'>User not found, or bad credentials - graphics/ccc.gif try again!</b></p>" 16:  End Sub 17: 18:  Protected Sub Signout_OnClick(Sender As Object, E As EventArgs) 19:   FormsAuthentication.SignOut() 20:   HttpContext.Current.Response.Redirect("login_xml.aspx") 21:  End Sub 22: </script> [C#] 01: <%@ Import Namespace="System.Data" %> 02: 03: <script runat="server" language="C#"> 04:  protected void Login_OnClick(Object sender, EventArgs e){ 05:   DataSet ds = new DataSet(); 06:   ds.ReadXml(Server.MapPath("Users.xml")); 07: 08:   int i; 09:   for(i=0; i < ds.Tables["User"].Rows.Count; i++){ 10:    if(ds.Tables["User"].Rows[i]["Email"].ToString() == UserName.Text.Trim() && graphics/ccc.gif ds.Tables["User"].Rows[i]["Password"].ToString() == Password.Text.Trim()){ 11: FormsAuthentication.RedirectFromLoginPage(UserName.Text, PersistCookie.Checked); 12:    } 13:   } 14: 15:   ErrorMsg.Text = "<p><b><font color='#CC3300'>User not found, or bad credentials - graphics/ccc.gif try again!</b></p>"; 16:  } 17: 18:  protected void Signout_OnClick(Object sender, EventArgs e){ 19:   FormsAuthentication.SignOut(); 20: HttpContext.Current.Response.Redirect("login_xml.aspx"); 21:  } 22: </script> 

In Listing 15.9 you authenticate users against an XML file. On line 6 you read the Users.xml file into a DataSet using the DataSet.ReadXml() method. This creates a DataTable named "User", with a row for each <User> element in the XML file. On line 9 you begin to iterate through the User DataTable . On line 10 you evaluate the current record for a matching e-mail address and password. If a complete match is found, you issue an authentication ticket using the FormsAuthentication.RedirectFromLoginPage() method. If no matches are found, the code executes down to the ErrorMsg on line 15, and an error message is displayed to the user.

only for RuBoard


Programming Data-Driven Web Applications with ASP. NET
Programming Data-Driven Web Applications with ASP.NET
ISBN: 0672321068
EAN: 2147483647
Year: 2000
Pages: 170

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net