The
key membership feature is the ability of ASP.NET to store user
credentials in a database. The idea is that you make a few choices
about the information that will be stored and the security policy that
will be used. From that point on, ASP.NET manages the user database for
you—adding new user information, checking credentials when users try to
log in, and so on.
Clearly, the membership
data store has the ability to greatly reduce the amount of code you
need to write. You can create a secure website with much less code and,
hence, much less work. You also don't need to worry about inevitable
bugs, because the ASP.NET membership module is a well-known, carefully
tested component.
So, why wouldn't you want to use the membership data store? A few possible reasons exist:
You don't want to store your user data in a database:
In theory, you can store
your user list in any type of data store, from an XML file to an Oracle
database. Technically, each data store requires a different membership
provider. However, ASP.NET includes only two providers—the SQL Server
provider you'll use in this chapter and a provider for Active
Directory. If you want to use another data store, such as a different
relational database, you'll need to find a corresponding membership, or
you'll need to forgo membership altogether.
You need backward compatibility:
If you've already created
a table to store user information, it may be too much trouble to switch
over to the membership data store. That's because the SQL Server
membership provider expects a specific table structure. It won't work
with existing tables, because they'll have a subtly different
combination of fields and data types. And even if you don't need to
keep the current table structure, you might find it's just too much
work to re-create all your user records in the membership data store.
You want to manage user information in non-ASP.NET applications:
As you'll see in this
chapter, ASP.NET gives you a powerful set of objects for interacting
with membership data. For example, you can update user records, delete
user records, retrieve user records based on certain criteria, and so
on. You can even use the membership objects in other types of .NET
applications (for example, you can create a Windows application to
manage user accounts). However, if you're creating another application
outside .NET that needs to perform these tasks, you might find it's not
as easy, because you'll need to understand the membership table
structure. In this case, you may find that it's easier to manage users
with straight SQL statements that work with your own table.
If you decide not to
use the membership data store, it's up to you to write ADO.NET code to
retrieve user records and check user credentials.
Before continuing any
further, you should set up your website to use forms authentication by
adding the <forms> tag. Here's what you need to add:
<configuration>
<system.web>
<authentication mode="Forms" />
...
</system.web>
</configuration>
1. Membership with SQL Server Express
Assuming you do decide to
use membership, you need to create the membership database. If you're
using SQL Server Express (the free version of SQL Server that's
included with Visual Studio), the task is a lot easier than you might
expect. In fact, it all happens automatically.
By default, membership is
enabled for every new website you create. The default membership
provider makes the following assumptions:
You want to store your membership database using SQL Server Express.
SQL
Server Express is installed on the current computer, with the instance
name SQLEXPRESS. (Usually, you'll install SQL Server Express when you
run the Visual Studio setup program.)
Your
membership data store will be a file named aspnetdb.mdf, which will be
stored in the App_Data subfolder in your web application directory.
These assumptions make a lot of
sense. They allow you to create as many web applications as you want
while still keeping the user databases separate. That's because each
website will have its own aspnetdb.mdf file. These files are never
registered in SQL Server, which means when you open a connection in
another application, you won't see dozens of user databases. Instead,
the only way to connect to them is to specify the file path in the
connection string, which ASP.NET does.
Another advantage of this
setup is that it's potentially easier to deploy your website. Assuming
the web server where you'll deploy your application has SQL Server
Express, you won't need to change the connection string. You also don't
need to perform any extra steps to install the database—you simply copy
the aspnetdb.mdf file with your website. This is clearly a great
advantage for large web hosting companies, because it's otherwise quite
complex to support multiple websites, each with its own custom database
that needs to be installed and maintained.
To see how this works, it
helps to create a new web project with a simple test page. Drag the
CreateUserWizard control onto your page from the Login section of the
Toolbox. Now run the page (shown in Figure 1), without adding any code or configuring the control.
Fill in all the text
boxes with user information. Note that by default you need to supply a
password that includes at least one character that isn't a number or a
letter (such as an underscore or an asterisk) and is at least seven
characters long. Once you've filled in all the information, click
Create User.
At this point, the
CreateUserWizard control uses the ASP.NET Membership class behind the
scenes to create a new user. The default membership provider creates
the aspnetdb.mdf file (if it doesn't exist already) and then adds the
new user record. Once this process is complete, the CreateUserWizard
control shows a message informing you that the user was created.
Miraculously, all of this takes place automatically even though you
haven't configured anything in the web.config file and you didn't
create the database file in advance.
To reassure yourself that the
user really was created, you can check for the aspnetdb.mdf file. In
the Solution Explorer, right-click the App_Data folder, and select
Refresh Folder. You'll see the aspnetdb.mdf file appear immediately.
Using Visual Studio, you can even dig into the contents of the
aspnetdb.mdf file. To do so, double-click the file in the Solution
Explorer. Visual Studio will configure a new connection and add it to
the Server Explorer on the left. Using the Server Explorer, you can
roam freely through the database, examining its tables and stored
procedures. (Remember, the Server Explorer window is called Database
Explorer in Visual Studio Web Developer Express, even though the window
works the same way.)
You can check the
aspnet_Users table to find the user record you created. Just
right-click the table name, and choose Show Table Data. You'll see
something like the record shown in Figure 2.
Among other details, you'll find a randomly generated GUID that
uniquely identifies the user and the date the user last used your web
application. You won't see the password and password question—that's
stored in a linked record in the aspnet_Membership table, and it's
encrypted to prevent casual snooping.
NOTE
At first glance,
you'll find the membership database includes a dizzying number of
tables.
Before diving into
the rest of ASP.NET's membership features in detail, it's important to
consider what you should do if you don't want the default membership
data store. For example, you might decide to store your membership
tables in a different database, or you might want to configure one of
the many options for the membership provider. You'll learn how to do so
in the next two sections.
2. Using the Full Version of SQL Server
If you're
using the automatically generated database for SQL Server Express, you
don't need to touch the web.config file. In any other case, you'll need
to do a bit of configuration tweaking.
The simplest case is if you're
using the full version of SQL Server. In this case, you can still use
the default membership settings. However, you need to change the
connection string.
The default membership
settings and local connection string are set in the machine.config
file. You can take a look at this file (and even edit it to update the
settings for all web applications on your computer). Look in the
c:\Windows\Microsoft.NET\Framework\[Version[\Config directory, where
[Version] is the version of ASP.NET that's installed, such as
v4.0.30319. Or, if you're configuring a deployed web application using
IIS on a 64-bit operating system, look in the
c:\Windows\Microsoft.NET\Framework64\[Version[\Config directory.
|
|
The default connection
string that's used with membership is named LocalSqlServer. You can
edit this setting directly in the machine.config. However, if you just
need to tweak it for a single application, it's better to adjust the
web.config file for your web application. First, you need to remove all
the existing connection strings using the <clear> element. Then,
add the LocalSqlServer connection string—but this time with the right
value:
<configuration>
<connectionStrings>
<clear />
<add name="LocalSqlServer" providerName="System.Data.SqlClient"
connectionString="Data Source=localhost;Integrated Security=SSPI;
Initial Catalog=aspnetdb" />
</connectionStrings>
...
</configuration>
This
<connectionStrings> section removes all connection strings and
then creates a new connection string. This new connection string
connects to a database named aspnetdb on the local computer. The only
catch is that the aspnetdb database won't be created automatically.
Instead, you'll need to generate it with the aspnet_regsql.exe
command-line tool. Rather than hunt around for this file, the easiest
way to launch it is to fire up the Visual Studio command prompt (open
the Start menu and choose All Programs => Microsoft Visual Studio 2010 => Visual Studio Tools => Visual Studio Command Prompt). You can then type in commands that use aspnet_regsql.
You can use aspnet_regsql in
two ways. If you use it without adding any command-line parameters, a
Windows wizard will appear that leads you through the process. You'll
be asked to supply the connection information for your database server.
The database will be named aspnetdb, which is the recommended default.
Your other option is to
specify exactly what you want to happen using command-line switches.
This is particularly useful when deploying your application—you can use
aspnet_regsql as part of a setup batch file, which will then create the
membership data store automatically. This is the option you'll use if
you want to choose the database name or if you want to install only
some of the database tables. By default, the aspnet_regsql tool
installs tables that can be used for user authentication, role-based
authorization, profiles, and Web Parts personalization. This gives you
maximum flexibility, but you may feel it's overkill if you aren't
planning to use some of these features.
Table 1
describes the most important command-line options. Here's an example
command line that connects to an unnamed SQL Server instance on the
current computer (using the -S parameter), connects with the current
Windows account (using the -E parameter), installs all tables (using
the -A all parameter), and places them all in a database named aspnetdb (which is the default):
aspnet_regsql -S (local) -E -A all
If you want to use a different database, you must specify the database name using the -d parameter.
It's a good idea to install all the tables at once (using the –A all
option). This way, your database will be ready for the profile feature
discussed in the next chapter. Once you've finished testing your
application and you're ready to create the final database, you can
create a database that only has the options you've decided to use. (For
example, use –A mr to use membership and role management but nothing else.)
|
|
Table 1. Command-Line Switches for aspnet_regsql.exe
Switch | Description |
---|
-S ServerName | Specifies the location of the SQL Server instance where you want to install the database. |
-E | Connects to the server through Windows authentication, using the currently logged-in Windows account. |
-U UserName and -P Password | Specify the user name and password you need to connect to the SQL Server database. Usually, you'll use -E instead. |
-A | Specifies
the features you want to use (and determines the database tables that
are created). Valid options for this switch are all, m (membership), r
(role-based security), p (profiles), c (Web Part personalization), and
w (for database cache dependencies with SQL Server 2000). |
-R | Removes the databases that support the features specified by the -A switch. |
-d DatabaseName | Allows
you to specify the name of the database in which the tables will be
created. If you don't specify this parameter, a database named aspnetdb
is created automatically. |
-sqlexportonly | Creates
SQL scripts for adding or removing the specified features to the
database, but doesn't actually create the tables in the database.
Instead, you can run the script afterward. This can be a useful
technique when deploying your application. |
NOTE
If you're deploying your
website to a web hosting company, you probably won't be allowed to run
aspnet_regsql on the web server. Instead, you'll probably need to use
SQL Server Express. In this case, your database will be deployed in the
App_Data folder as part of your web application, and no extra
configuration steps will be required. If your web host doesn't support
SQL Server Express, you'll need to use a tool like SQL Server
Management Studio to prepare a .sql script file that installs your
database. The administrators at the web hosting company can then run
your script file to create the database you need.
3. Configuring the Membership Provider
Configuring the connection
string is the simplest change you can make when setting up the
membership data store. However, you may also want to tweak other
membership settings. For example, you can change the default password
policy.
NOTE
As with the connection
string, the default membership provider is defined in the
machine.config file. You can edit the machine.config file to change
these defaults for all applications on the computer, but you shouldn't,
because it will complicate your life when you deploy the application.
Instead, you should make the changes by configuring a new membership
provider in your application's web.config file.
To configure your
membership provider, you need to add the <membership> element to
your web application. Inside the <membership> element, you define
a new membership provider with your custom settings. Then, you set the
defaultProvider attribute of the <membership> element so it
refers to your membership provider by name.
Here's the basic structure you need to follow:
<configuration>
<system.web>
<membership defaultProvider="MyMembershipProvider">
<providers>
<!-- Clear any existing providers. -->
<clear />
<!-- Define your provider, with custom settings. -->
<add name="MyMembershipProvider" ... />
</providers>
</membership>
...
</system.web>
</configuration>
Of course, the interesting part
is the attributes you use in the <add> tag to configure your
membership provider. Here's an example that defines a membership
provider with relaxed password settings. The first three attributes
supply required settings (the name, type, and connection string for the
membership provider). The remaining settings remove the requirement for
a security question and allow a password to be as short as one
character and contain only letters and numbers:
<membership defaultProvider="MyMembershipProvider">
<providers>
<clear/>
<add
name="MyMembershipProvider"
type="System.Web.Security.SqlMembershipProvider"
connectionStringName="LocalSqlServer"
requiresQuestionAndAnswer="false"
minRequiredPasswordLength="1"
minRequiredNonalphanumericCharacters="0" />
</providers>
</membership>
Table 2 describes the most commonly used membership settings.
Table 2. Attributes for Configuring a Membership Provider
Attribute | Description |
---|
name | Specifies
a name for the membership provider. You can choose any name you want.
This is the name you use later to reference the provider (for example,
when you set the defaultProvider attribute). You can also use it to get
provider information programmatically. |
type | Specifies
the type of membership provider. In this chapter, you will always be
using the System.Web.Security.SqlMembershipProvider. ASP.NET also
includes an ActiveDirectoryMembershipProvider, which allows you to use
the membership features with Windows authentication through an Active
Directory server. (For more information on this topic, consult the
Visual Studio Help.) Finally, you can use a custom membership provider
that you or a third-party developer creates. |
applicationName | Specifies
the name of the web application. This setting is primarily useful if
you have several web applications using the same membership database.
If you give each one a separate application name, all the information
(including user, profiles, and so on) is completely separated so it's
usable only in the appropriate application. |
connectionStringName | Specifies
the name of the connection string setting. This must correspond to a
connection string defined in the <connectionStrings> section of
web.config or machine.config. |
description | Allows an optional description for the membership provider. |
passwordFormat | Sets
the way passwords are stored in the database. You can use Clear
(passwords are stored as is, with no encryption), Encrypted (passwords
are encrypted using a computer-specific key), or Hashed (passwords are
hashed, and the hash value is stored in the database). Hashing
passwords offers similar protection to encrypting them (namely, if you
look at the hash you'll have a difficult time reverse-engineering the
password). However, when passwords are hashed, they can never be
retrieved—only reset. |
minRequiredPasswordLength | Specifies
the minimum length of a password. If the user enters fewer characters
when creating an account, the attempt will be rejected with an error
message. |
minRequiredNonalphanumericCharacters | Specifies
the number of nonalphanumeric characters (characters other than numbers
and letters) the password needs to have. If the user enters fewer of
these characters when creating an account, the attempt will be rejected
with an error message. Although requiring nonalphanumeric characters
makes for stronger (less guessable) passwords, it also can confuse
users, causing them to forget their passwords more often or (worse)
write them down in a conspicuous place, where they might be stolen. |
maxInvalidPasswordAttempts | Specifies
the number of times a user is allowed to enter an invalid password for
their login before the user account is locked and made inaccessible.
The default is 5 attempts. |
passwordAttemptWindow | Sets
the internal time in which maxInvalidPasswordAttempts is measured. For
example, if you set a window of 30 minutes, after 30 minutes the number
of invalid password attempts is reset. If the user surpasses the
maxInvalidPasswordAttempts within passwordAttemptWindow, the account is
locked. |
enablePasswordReset | Determines whether a password can be reset, which is useful if a password is forgotten. |
enablePasswordRetrieval | Determines
whether a password can be requested (and e-mailed to the user), which
is useful if a user forgets a password. This feature is never supported
if passwordFormat is set to Hashed, because the password isn't stored
in that case. |
requiresQuestionAndAnswer | Determines whether the membership security answer will be required when you request or reset a user password. |
requiresUniqueEmail | If
false, allows more than one user to have the same e-mail address. The
e-mail address information is always optional. (However, the
CreateUserWizard control requires an email address unless you set
RequireEmail to False.) |
|
Now that you've seen the
settings you can tweak, it's worth asking what the defaults are. If you
look at the <membership> section in the machine.config file,
here's what you'll find:
<membership>
<providers>
<add name="AspNetSqlMembershipProvider"
type="System.Web.Security.SqlMembershipProvider ..."
connectionStringName="LocalSqlServer"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="true"
applicationName="/"
requiresUniqueEmail="false"
passwordFormat="Hashed"
maxInvalidPasswordAttempts="5"
minRequiredPasswordLength="7"
minRequiredNonalphanumericCharacters="1"
passwordAttemptWindow="10" />
</providers>
</membership>
As you
can see, the default membership provider is
AspNetSqlMembershipProvider. It connects using the LocalSqlServer
connection string and supports password resets but not password
retrieval. Accounts require a security question but not a unique
e-mail. The passwords themselves are hashed in the database for
security, so they can't be retrieved. Passwords must be at least seven
characters long with at least one nonalphanumeric character. Finally,
if a user makes five invalid password attempts in ten minutes, the
account is disabled.
4. Creating Users with the WAT
Once you've created the
membership data store and (optionally) configured the membership
provider, you're ready to use membership-backed security in your web
application. As you've already seen, you can create new users with the
CreateUserWizard control. You'll consider the CreateUserWizard control
and the other security controls later in this chapter. First, it's
worth considering your other options for setting up your user list.
One option is to use the WAT. Choose Website =>
ASP.NET Configuration to launch this tool. Next, click the Security
tab. In the bottom-left corner, a box indicates how many users are
currently in the database (see Figure 3). This box also provides links that allow you to examine the existing user records or add new ones.
If you want to browse the
current user list or update an existing user record, click the Manage
Users link. To add new users, click Create User. You'll see a set of
controls that are similar to the CreateUserWizard control used in the
test page earlier (see Figure 4).
After you've created a few users, you may want to take another look at
the aspnet_Users and aspnet_Membership tables in your database to see
what the user records look like.
Although the WAT is a
perfectly sensible way to add user records, you might find the web
interface is a little sluggish if you have a large number of users to
create. Another option is to use the Membership class, as shown here:
' Create a user record based with user name, password, and e-mail information.
Membership.CreateUser(userName, password, email)
Here's an example with hard-coded values:
Membership.CreateUser("joes", "ignreto12__", "joes@domains.com")
This creates a new user with
just a single line of code. Of course, the CreateUser() method has
multiple overloads, which you can use to supply details such as the
password question and answer. If you haven't changed the default
membership settings, you won't be able to create an account unless you
provide these details. Instead, you'll need to use this more complex
overload:
Dim createStatus As MembershipCreateStatus
Membership.CreateUser("joes", "ignreto12__", "joes@domains.com", _
"What is your favorite restaurant?", "Saigon", True, createStatus)
The first few parameters are
self-explanatory—they take the user name, password, e-mail address,
password question, and password answer. The second-to-last parameter
takes a Boolean value that determines whether the account is given the
IsApproved flag. If you supply False, the account won't be approved,
and so it won't be active (and usable) until you modify it using the
Membership.UpdateUser() method. In the simpler overload that doesn't
include this parameter, accounts are always marked as approved.
The last parameter returns
a value from the MembershipCreateStatus enumeration. If this value
isn't MembershipCreateStatus.Success, an error occurred when creating
the record. The value indicates the exact error condition (for example,
a password that wasn't strong enough, a duplicate e-mail address when
your membership provider doesn't allow duplicates, and so on). In the
simpler overload that doesn't include the MembershipCreateStatus, any
error results in an exception object being thrown that has the same
information.
Clearly, if you needed to
transfer a large number of user accounts from a custom database into
the membership data store, the quickest option would be to write a
routine that loops through the existing records and use the
CreateUser() method to insert the new ones.
|
|
5. The Membership and MembershipUser Classes
There wouldn't be much point
to using the membership data store if you still needed to write
handcrafted ADO.NET code to retrieve or modify user information. That's
why ASP.NET offers a more convenient, higher-level model with the
Membership class.
Membership is a useful
class that's full of practical shared methods such as CreateUser(). You
can find it in the System.Web.Security namespace. Table 3 provides a snapshot of its most useful shared methods.
Table 3. Membership Methods
Method | Description |
---|
CreateUser() | Adds a new user to the database. |
DeleteUser() | Deletes
an existing user from the database. You specify the user by the user
name. You can also choose whether you want to delete all related data
in other tables (the default is to remove it). |
UpdateUser() | Updates the database with new information for a specific user. |
GetUser() | Gets a specific user from the database, by user name. |
GetUserNameByEmail() | Retrieves
a user name for the user that matches a given e-mail address. Keep in
mind that duplicate e-mail addresses are allowed by default, in which
case this method will find only the first match. |
FindUsersByName() | Gets
users from the membership database that match a given user name. This
supports partial matches, so User will match TestUser, User001, and so
on. |
FindUsersByEmail() | Gets
users from the membership database that match a specific e-mail
address. You can also supply part of an e-mail address (such as the
domain name), in which case you'll get every user who has an e-mail
address that contains this text. |
GetAllUsers() | Gets
a collection that represents all the users in the database. An
overloaded version of this method allows you to get just a portion of
the full user list (a single page of users, based on a starting index
and length). |
GetNumberOfUsersOnline() | Gets
the number of logged-in users currently accessing an application. This
calculation assumes a user is online if that user's last activity time
stamp falls within a set time limit (such as 20 minutes). |
GeneratePassword() | Generates a random password of the specified length. This is useful when programmatically creating new user records. |
ValidateUser() | Check
whether the supplied user name and password exist in the database. You
can use this method to write your authentication logic in the login
page. |
The Membership class also
provides shared read-only properties that let you retrieve information
about the configuration of your membership provider, as set in the
configuration file. For example, you can retrieve the required password
length, the maximum number of password attempts, and all the other
details described in Table 20-2.
Many of these
methods use the MembershipUser class, which represents a user record.
For example, when you call GetUser(), you receive the information as a
MembershipUser object. If you want to update that user, you can change
its properties and then call Membership.UpdateUser() with the modified
MembershipUser object.
NOTE
The MembershipUser
object combines the details from the aspnet_Users table and the linked
aspnet_Membership table. For example, it includes the password
question. However, the password answer and the password itself aren't
available.
The MembershipUser class also provides its own smaller set of instance methods. The most important ones are detailed in Table 4.
Table 4. Membership User Methods
Method | Description |
---|
UnlockUser() | Reactivates a user account that was locked out for too many invalid login attempts. |
GetPassword() | Retrieves
a user password. If requiresQuestionAndAnswer is true in the membership
configuration (which is the default), you must supply the answer to the
password question in order to retrieve a password. Note that this
method won't work at all if the passwordFormat setting is Hashed or if
enablePasswordRetrieval is set to false, which is also the default. |
ResetPassword() | Resets
a user password using a new, randomly generated password, which this
method returns. If requiresQuestionAndAnswer is true in the membership
configuration (which is the default), you must supply the answer to the
password question in order to reset a password. You can display the new
password for the user or send it in an e-mail. |
ChangePassword() | Changes a user password. You must supply the current password in order to apply a new one. |
ChangePasswordQuestionAndAnswer() | Changes a user password question and answer. You must supply the current password in order to change the security question. |
To get a sense of how the
Membership class works, you can create a simple test page that displays
a list of all the users in the membership database. Figure 5 shows this page.
To create this page, you
simply need to begin by defining the GridView. The GridView will show a
list of MembershipUser objects. For each user, it shows the values from
the UserName and Email properties, along with a Select link. Here's the
markup that creates the GridView (without the formatting details):
<asp:GridView ID="gridUsers" runat="server"
AutoGenerateColumns="False" DataKeyNames="UserName" >
<Columns>
<asp:BoundField DataField="UserName" HeaderText="User Name" />
<asp:BoundField DataField="Email" HeaderText="Email" />
<asp:CommandField ShowSelectButton="True" />
</Columns>
</asp:GridView>
When the page is first
loaded, it calls the Membership.GetAllUsers() method and binds the
results to the GridView, as shown here:
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
gridUsers.DataSource = Membership.GetAllUsers()
gridUsers.DataBind()
End Sub
To make the example more
interesting, when a record is selected, the corresponding
MembershipUser object is retrieved. This object is then added to a
collection so it can be bound to the DetailsView for automatic display:
Protected Sub gridUsers_SelectedIndexChanged(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles gridUsers.SelectedIndexChanged
Dim list As New List(Of MembershipUser)()
list.Add(Membership.GetUser(gridUsers.SelectedValue.ToString()))
detailsUser.DataSource = list
detailsUser.DataBind()
End Sub
Here's the DetailsView that does the work (again, without the formatting details):
<asp:DetailsView ID="detailsUser" runat="server"></asp:DetailsView>
This DetailsView uses
automatic row creation (because AutoGenerateRows defaults to True). As
a result, the DetailsView shows all the MembershipUser properties.
Figure 6
shows the information that's available in a single record. Among other
details, you can use the MembershipUser object to check whether a user
is online, when they last accessed the system, and what their e-mail
address is.
6. Authentication with Membership
Now that you've switched
to membership, and all your users are stored in the membership data
store, you need to change the way your login page works. Life now gets
a lot simpler—rather than create ADO.NET objects to query a database
and see whether a matching user record exists, you can let the
Membership class perform all the work for you. The method you need is
Membership.ValidateUser(). It takes a user name and password and
returns True if there's a valid match in the database.
Here's the new code you need in your login page:
Protected Sub cmdLogin_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles cmdLogin.Click
If Membership.ValidateUser(txtName.Text, txtPassword.Text) Then
FormsAuthentication.RedirectFromLoginPage(txtName.Text, False)
Else
lblStatus.Text = "Invalid username or password."
End If
End Sub
Actually, a fair bit of work
is taking place behind the scenes. If you're using the default
membership provider settings, passwords are hashed. That means when you
call ValidateUser(), ASP.NET hashes the newly supplied password using
the same hashing algorithm and then compares it to the hashed password
that's stored in the database.
7. Disabled Accounts
An account can become disabled in the membership database in two ways:
The account isn't approved:
This
occurs if you create an account programmatically and supply False for
the isApproved parameter. You might take this step if you want to
create an account automatically but allow an administrator to review it
before it becomes live. To make this account active, you need to get a
MembershipUser object for the corresponding user record, set
MembershipUser.IsApproved to True, and call Membership.UpdateUser().
The account is locked out:
This occurs if the user
makes multiple attempts to access a user account with an invalid
password. In this case, you need to get a MembershipUser object for the
user, and call MembershipUser.UnlockUser(). You may also want to call
MembershipUser.ResetPassword() to prevent another lockout.
To help you with these tasks, you might want to create an administrative page like the one shown in Figure 20-6. For example, you can allow a user to review all accounts that aren't yet approved and approve them by clicking a button.
Similarly, if you want to
disable an account at any time, you can retrieve a MembershipUser
object for that user and set the IsApproved property to False. However,
you have no way to programmatically lock a user account.
You're probably already thinking
of a wide range of pages you can create using the Membership and
MembershipUser classes. For example, you can build pages that allow
users to request a password reset or check whether they are locked out.
However, you might not need to create all these pages, because ASP.NET
includes a rich set of security controls that automate many common
tasks. You'll learn more about the security controls in the next
section.