If TextBox1.Text = "BillEvjen" And TextBox2.Text = "Bubbles" ThenFormsAuthentication.RedirectFromLoginPageTextBox1.Text, True Else Response.Write"Invalid credentials" End If End Sub L
Trang 1Attribute Description
timeout Specifies the amount of time, in minutes, after which the cookie expires The
default value is30
cookieless Specifies whether the forms-based authentication process should use cookies
when working with the authentication/authorization process
defaultUrl Specifies the default URL
domain Specifies the domain name to be sent with forms authentication cookies
slidingExpiration Specifies whether to apply a sliding expiration to the cookie If set toTrue,
the expiration of the cookie is reset with each request made to the server The default value isFalse
enableCross
AppsRedirect Specifies whether to allow for cross-application redirection
requireSSL Specifies whether a Secure Sockets Layer (SSL) connection is required when
transmitting authentication information
After theweb.configfile is in place, the next step is to create a typical page for your application that
people can access Listing 21-4 presents a simple page
Listing 21-4: A simple page — Default.aspx
<%@ Page Language="VB" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>The Application</title>
</head>
<body>
<form id="form1" runat="server">
<div>
Hello World
</div>
</form>
</body>
</html>
As you can see, this page simply writesHello Worldto the browser The real power of forms
authentica-tion is shown in theLogin.aspxpage presented in Listing 21-5
Listing 21-5: The Login.aspx page
VB
<%@ Page Language="VB" %>
<script runat="server">
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
Trang 2If (TextBox1.Text = "BillEvjen" And TextBox2.Text = "Bubbles") Then
FormsAuthentication.RedirectFromLoginPage(TextBox1.Text, True) Else
Response.Write("Invalid credentials") End If
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Login Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
Username<br />
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox><br />
<br />
Password<br />
<asp:TextBox ID="TextBox2" runat="server"
TextMode="Password"></asp:TextBox><br />
<br />
<asp:Button ID="Button1" OnClick="Button1_Click" runat="server"
Text="Submit" />
</div>
</form>
</body>
</html>
C#
<%@ Page Language="C#"%>
<script runat="server">
protected void Button1_Click(object sender, EventArgs e)
{
if (TextBox1.Text == "BillEvjen" && TextBox2.Text == "Bubbles") {
FormsAuthentication.RedirectFromLoginPage(TextBox1.Text, true);
}
else {
Response.Write("Invalid credentials");
}
}
</script>
Login.aspxhas two simple TextBox controls and a Button control that asks the user to submit his
username and password TheButton1_Clickevent uses theRedirectFromLoginPagemethod of the
FormsAuthenticationclass This method does exactly what its name implies — it redirects the request fromLogin.aspxto the original requested resource
RedirectFromLoginPagetakes two arguments The first is the name of the user, used for cookie authenti-cation purposes This argument does not actually map to an account name and is used by ASP.NET’s URL authorization capabilities The second argument specifies whether a durable cookie should be issued
If set toTrue, the end user does not need to log in again to the application from one browser session
to the next
Trang 3Using the three pages you have constructed, each request for theDefault.aspxpage from Listing 21-4
causes ASP.NET to check that the proper authentication token is in place If the proper token is not found,
the request is directed to the specified login page (in this example,Login.aspx) Looking at the URL
in the browser, you can see that ASP.NET is using a querystring value to remember where to return the
user after he has been authorized to proceed:
http://localhost:35089/Security/Login.aspx?ReturnUrl=%2fSecurity%2fDefault.aspx
Here, the querystringReturnUrlis used with a value of the folder and page that was the initial request
Look more closely at theLogin.aspxpage from Listing 21-5, and note that the values placed in the two
text boxes are checked to make sure they abide by a specific username and password If they do, the
RedirectFromLoginPagemethod is invoked; otherwise, theResponse.Write()statement is used In
most cases, you do not want to hardcode a username and password in your code Many other options
exist for checking whether usernames and passwords come from authorized users Some of the other
options follow
Authenticating Against Values Contained in the web.config File
The previous example is not the best approach for dealing with usernames and passwords offered for
authentication It is never a good idea to hardcode these things directly into your applications Take a
quick look at storing these values in theweb.configfile itself
The<forms>element inweb.configthat you worked with in Listing 21-3 can also take a sub-element
The sub-element,<credentials>, allows you to specify username and password combinations directly
in theweb.configfile You can choose from a couple of ways to add these values The simplest method
is shown in Listing 21-6
Listing 21-6: Modifying the web.config file to add username/password values
<system.web>
<authentication mode="Forms">
<forms name="Wrox" loginUrl="Login.aspx" path="/">
<credentials passwordFormat="Clear">
<user name="BillEvjen" password="Bubbles" />
</credentials>
</forms>
</authentication>
<authorization>
<deny users="?" />
</authorization>
</system.web>
The<credentials>element has been included to add users and their passwords to the configuration
file.<credentials>takes a single attribute —passwordFormat The possible values ofpasswordFormat
areClear,MD5, andSHA1 The following list describes each of these options:
❑ Clear: Passwords are stored in clear text The user password is compared directly to this value
without further transformation
❑ MD5: Passwords are stored using a Message Digest 5 (MD5) hash digest When credentials are
validated, the user password is hashed using the MD5 algorithm and compared for equality with
Trang 4this value The clear-text password is never stored or compared This algorithm produces better performance than SHA1
❑ SHA1: Passwords are stored using the SHA1 hash digest When credentials are validated, the
user password is hashed using the SHA1 algorithm and compared for equality with this value
The clear-text password is never stored or compared Use this algorithm for best security
In the example from Listing 21-6, you use a setting ofClear This is not the most secure method, but it is used for demonstration purposes A sub-element of<credentials>is<user>; that is where you define the username and password for the authorized user with the attributesnameandpassword
The next step is to change theButton1_Clickevent on theLogin.aspxpage shown earlier This is illus-trated in Listing 21-7
Listing 21-7: Changing the Login.aspx page to work with the web.config file
VB
<%@ Page Language="VB" %>
<script runat="server">
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
If FormsAuthentication.Authenticate(TextBox1.Text, TextBox2.Text) Then
FormsAuthentication.RedirectFromLoginPage(TextBox1.Text, True) Else
Response.Write("Invalid credentials") End If
End Sub
</script>
C#
<%@ Page Language="C#"%>
<script runat="server">
protected void Button1_Click(object sender, EventArgs e)
{
if (FormsAuthentication.Authenticate(TextBox1.Text, TextBox2.Text)) {
FormsAuthentication.RedirectFromLoginPage(TextBox1.Text, true);
}
else {
Response.Write("Invalid credentials");
}
}
</script>
In this example, you simply use theAuthenticate()method to get your ASP.NET page to look at
the credentials stored in theweb.configfile for verification TheAuthenticate()method takes two
parameters — the username and the password that you are passing in to be checked If the credential
lookup is successful, theRedirectFromLoginPagemethod is invoked
It is best not to store your users’ passwords in theweb.configfile as clear text as the preceding example did Instead, use one of the available hashing capabilities so you can keep the end user’s password out of
Trang 5sight of prying eyes To do this, simply store the hashed password in the configuration file as shown in
Listing 21-8
Listing 21-8: Using encrypted passwords
<forms name="Wrox" loginUrl="Login.aspx" path="/">
<credentials passwordFormat="SHA1">
<user name="BillEvjen" password="58356FB4CAC0B801F011B397F9DFF45ADB863892" />
</credentials>
</forms>
Using this kind of construct makes it impossible for even the developer to discover a password because
the clear text password is never used TheAuthenticate()method in theLogin.aspxpage hashes the
password using SHA1 (because it is the method specified in theweb.config’s<credentials>node) and
compares the two hashes for a match If a match is found, the user is authorized to proceed
When using SHA1 or MD5, the only changes you make are in theweb.configfile and nowhere else
You do not have to make any changes to the login page or to any other page in the application To store
hashed passwords, however, you use the
FormsAuthenticationHashPasswordForStoringInConfig-Filemethod (probably the longest method name in the NET Framework) You accomplish this in the
following manner:
FormsAuthentication.HashPasswordForStoringInConfigFile(TextBox2.Text, "SHA1")
Authenticating Against Values in a Database
Another common way to retrieve username/password combinations is by getting them directly from a
datastore of some kind This enables you, for example, to check the credentials input by a user against
values stored in Microsoft’s SQL Server The code for this is presented in Listing 21-9
Listing 21-9: Checking credentials in SQL Server (Login.aspx)
VB
<%@ Page Language="VB" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<script runat="server">
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
Dim conn As SqlConnection
Dim cmd As SqlCommand
Dim cmdString As String = "SELECT [Password] FROM [AccessTable] WHERE" & _
" (([Username] = @Username) AND ([Password] = @Password))"
conn = New SqlConnection("Data Source=localhost;Initial " & _
"Catalog=Northwind;Persist Security Info=True;User ID=sa") cmd = New SqlCommand(cmdString, conn)
cmd.Parameters.Add("@Username", SqlDbType.VarChar, 50)
cmd.Parameters("@Username").Value = TextBox1.Text
Trang 6cmd.Parameters.Add("@Password", SqlDbType.VarChar, 50)
cmd.Parameters("@Password").Value = TextBox2.Text
conn.Open()
Dim myReader As SqlDataReader
myReader = cmd.ExecuteReader(CommandBehavior.CloseConnection)
If myReader.Read() Then
FormsAuthentication.RedirectFromLoginPage(TextBox1.Text, False)
Else
Response.Write("Invalid credentials")
End If
myReader.Close()
End Sub
</script>
C#
<%@ Page Language="C#"%>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<script runat="server">
protected void Button1_Click(object sender, EventArgs e)
{
SqlConnection conn;
SqlCommand cmd;
string cmdString = "SELECT [Password] FROM [AccessTable] WHERE" +
" (([Username] = @Username) AND ([Password] = @Password))";
conn = new SqlConnection("Data Source=localhost;Initial " +
"Catalog=Northwind;Persist Security Info=True;User ID=sa");
cmd = new SqlCommand(cmdString, conn);
cmd.Parameters.Add("@Username", SqlDbType.VarChar, 50);
cmd.Parameters["@Username"].Value = TextBox1.Text;
cmd.Parameters.Add("@Password", SqlDbType.VarChar, 50);
cmd.Parameters["@Password"].Value = TextBox2.Text;
conn.Open();
SqlDataReader myReader;
myReader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
if (myReader.Read()) {
FormsAuthentication.RedirectFromLoginPage(TextBox1.Text, false);
}
else {
Response.Write("Invalid credentials");
}
Continued
Trang 7}
</script>
Leave everything else from the previous examples the same, except for theLogin.aspxpage You can
now authenticate usernames and passwords against data stored in SQL Server In theButton1_Click
event, a connection is made to SQL Server (For security reasons, you should store your connection string
in theweb.configfile.) Two parameters are passed in — the inputs fromTextBox1andTextBox2 If a
result is returned, theRedirectFromLoginPage()method is invoked
Using the Login Control with Forms Authentication
You have seen how to use ASP.NET forms authentication with standard ASP.NET server controls, such
as simple TextBox and Button controls You can also use the ASP.NET server controls — such as the
Login server control — with your custom-developed forms-authentication framework instead of using
other controls This really shows the power of ASP.NET — you can combine so many pieces to construct
the solution you want
Listing 21-10 shows a modifiedLogin.aspxpage using the new Login server control
Listing 21-10: Using the Login server control on the Login.aspx page
VB
<%@ Page Language="VB" %>
<script runat="server">
Protected Sub Login1_Authenticate(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.AuthenticateEventArgs)
If (Login1.UserName = "BillEvjen" And Login1.Password = "Bubbles") Then FormsAuthentication.RedirectFromLoginPage(Login1.UserName, _ Login1.RememberMeSet)
Else Response.Write("Invalid credentials") End If
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Login Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Login ID="Login1" runat="server" OnAuthenticate="Login1_Authenticate">
</asp:Login>
</div>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
Trang 8<script runat="server">
protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
{
if (Login1.UserName == "BillEvjen" && Login1.Password == "Bubbles") { FormsAuthentication.RedirectFromLoginPage(Login1.UserName, Login1.RememberMeSet);
} else { Response.Write("Invalid credentials");
} }
</script>
Because no Button server control is on the page, you use the Login control’sOnAuthenticateattribute
to point to the authentication server-side event —Login1_Authenticate The event takes care of the
authorization lookup (although the values are hardcoded in this example) The username text box of the Login control can be accessed via theLogin1.UserNamedeclaration, and the password can be accessed
usingLogin1.Password TheLogin1.RememberMeSetproperty is used to specify whether to persist the
authentication cookie for the user so that he is remembered on his next visit
This example is a bit simpler than creating your own login form using TextBox and Button controls You can give the Login control a predefined look-and-feel that is provided for you You can also get at the
subcontrol properties of the Login control a bit more easily In the end, it really is up to you as to what
methods you employ in your ASP.NET applications
Looking Closely at the FormsAuthentication Class
As you can tell from the various examples in the forms authentication part of this chapter, a lot of what goes on depends on theFormsAuthenticationclass itself For this reason, you should learn what that
class is all about
FormsAuthenticationprovides a number of methods and properties that enable you to read and
con-trol the authentication cookie as well as other information (such as the return URL of the request) The
following table details some of the methods and properties available in theFormsAuthentictationclass
Authenticate This method is used to authenticate credentials that are stored in a
configuration file (such as theweb.configfile)
Decrypt Returns an instance of a valid, encrypted authentication ticket retrieved
from an HTTP cookie as an instance of aFormsAuthenticationTicket
class
Encrypt Creates a string which contains a valid encrypted authentication ticket that
can be used in an HTTP cookie
FormsCookieName Returns the name of the cookie for the current application
FormsCookiePath Returns the cookie path (the location of the cookie) for the current
application
GetAuthCookie Provides an authentication cookie for a specified user
Trang 9Method/Property Description
GetRedirectUrl Returns the URL to which the user is redirected after being authorized by
the login page
HashPasswordFor
Storing InConfigFile
Creates a hash of a provided string password This method takes two parameters — one is the password and the other is the type of hash to perform on the string Possible hash values includeSHA1andMD5
Initialize Performs an initialization of theFormsAuthenticationclass by reading the
configuration settings in theweb.configfile, as well as getting the cookies and encryption keys used in the given instance of the application
RedirectFromLogin
Page
Performs a redirection of the HTTP request back to the original requested page This should be performed only after the user has been authorized to proceed
RenewTicketIfOld Conditionally updates the sliding expiration on a
FormsAuthenticationTicketinstance
RequireSSL Specifies whether the cookie should be transported via SSL only (HTTPS)
SetAuthCookie Creates an authentication ticket and attaches it to a cookie that is contained
in the outgoing response
SignOut Removes the authentication ticket
SlidingExpiration Provides a Boolean value indicating whether sliding expiration is enabled
Passport Authentication
Another method for the authentication of your end users is using Microsoft’s Passport identity system
Users with a passport account can have a single sign-on solution, meaning that he needs only those
credentials to log in to your site and into other Passport-enabled sites and applications on the Internet
When your application is enabled for Passport authentication, the request is actually redirected to the
Microsoft Passport site where the user can enter his credentials If the authentication is successful,
the user is then authorized to proceed, and the request is redirected back to your application
Very few Internet sites and applications use Microsoft’s Passport technologies In fact, Microsoft has
completely de-emphasized Passport in 2005, and most companies interested in global authentication/
authorization standards are turning toward the Project Liberty endeavors for a solution
(www.projectliberty.org)
Authenticating Specific F iles and Folders
You may not want to require credentials for each and every page or resource in your application
For instance, you might have a public Internet site with pages anyone can access without credentials,
although you might have an administration section as part of your application that may require
authen-tication/authorization measures
Trang 10URL authorization enables you to use theweb.configfile to apply the settings you need Using URL
authorization, you can apply any of the authentication measures to only specific files or folders
Listing 21-11 shows an example of locking down a single file
Listing 21-11: Applying authorization requirements to a single file
<configuration>
<system.web>
<authentication mode="None" />
<! The rest of your web.config file settings go here >
</system.web>
<location path="AdminPage.aspx">
<system.web>
<authentication mode="Windows" />
<authorization>
<allow users="ReutersServer \EvjenB" />
<deny users="*" />
</authorization>
</system.web>
</location>
</configuration>
Thisweb.configconstruction keeps the Web application open to the general public while, at the same
time, it locks down a single file contained within the application — theAdminPage.aspxpage This is
accomplished through the<location>element.<location>takes a single attribute (path) to specify
the resource defined within the <system.web> section of theweb.configfile
In the example, the<authentication>and<authorization>elements are used to provide the authen-tication and authorization details for theAdminPage.aspxpage For this page, Windows authentication
is applied, and the only user allowed access isEvjenBin theReutersServerdomain You can have as
many<location>sections in yourweb.configfile as you want
Programmatic Authorization
So far, you have seen a lot of authentication examples that simply provide a general authorization to a
specific page or folder within the application Yet, you may want to provide more granular authorization measures for certain items on a page For instance, you might provide a link to a specific document only for users who have an explicit Windows role Other users may see something else You also might want additional commentary or information for specified users, while other users see a condensed version of the information Whatever your reason, this role-based authorization practice is possible in ASP.NET by working with certain objects
You can use thePageobject’sUserproperty, which provides an instance of theIPrincipalobject The
Userproperty provides a single method and a single property:
❑ Identity: This property provides an instance of theSystem.Security.Principal.IIdentity
object for you to get at specific properties of the authenticated user