The
authentication examples you've examined so far provide an
all-or-nothing approach that either forbids or allows a user. In many
cases, however, an application needs to recognize different levels of
users. Some users will be provided with a limited set of capabilities,
and other users might be allowed to perform potentially dangerous
changes or use the administrative portions of a website.
To allow this type of
multitiered access, you need ASP.NET's role-based authorization
feature. As with membership, ASP.NET takes care of storing the role
information and making it available to your code. All you need to do is
create the roles, assign users to each role, and then test for role
membership in your code.
Before you can use role-based
authorization, you need to enable it. Although you can perform this
step using the WAT (just click the Enable Roles link in the Security
tab), it's easy enough just to add the required line to your web.config
file directly:
<configuration>
<system.web>
<roleManager enabled="true" />
...
</system.web>
...
</configuration>
As with the membership data
store, ASP.NET will automatically create the role information in the
aspnetdb.mdf file using SQL Server Express. If you want to use a
different database, you need to follow the steps discussed earlier in
this chapter to create the database using aspnet_regsql.exe and modify
the connection string.
1. Creating and Assigning Roles
Once you enable role
management, you need to create a basic set of roles (for example, User,
Administrator, Guest, and so on). You can then assign users to one or
more groups.
You can create roles in two ways. You can do so programmatically, or you can do so by hand, using the WAT.
To use the WAT, follow these steps:
Launch the WAT by selecting Website => ASP.NET Configuration.
Click the Create or Manage Roles link.
To add a new role, type it into the provided text box, and click Add Role (see Figure 1). Or use the Manage and Delete links in the role list to modify or delete an existing role record.
To place a user into a role,
you'll need to head back to the main security page (click the Back
button in the role management page). Then follow these steps:
Select Manage Users from the Security tab. You'll see the full list of users for your website (subdivided into pages).
Find the user you want to change, and click the Edit Roles link next to that user.
Fill in the check box for each role you want to assign to that user.
Figure 2 shows an example where the user joes is being given the User role.
Of course, you don't need to
use the WAT. You can also use the Roles class. The Roles class serves
the same purpose for role management as the Membership class does for
membership—it provides a number of shared utility methods that let you
modify role information. Table 1 lists the methods you can use.
Table 1. Methods of the Roles Class
Method | Description |
---|
CreateRole() | Adds a new role to the database. |
DeleteRole() | Deletes
an existing role from the database. If you want to delete a role that
currently has members assigned to it, you either need to remove the
users from the role first or use the overloaded version of DeleteRole()
that accepts the throwOnPopulatedRole parameter (which you must set to
False). |
RoleExists() | Checks whether a specific role name exists in the database. |
GetAllRoles() | Retrieves a list of all the roles for this application. |
AddUserToRole(), AddUserToRoles(), AddUsersToRole(), and AddUsersToRoles() | Assigns
a role to a user, assigns several roles to a user at once, assigns a
role to several users, or assigns several roles to several users. If
you want to assign a role to a large number of users, the quickest
approach is to use the Membership class to retrieve the corresponding
user names (if needed), and then use the AddUsersToRole() or
AddUsersToRoles() method of the Roles class to apply the change to
everyone at once. |
RemoveUserFromRole(), RemoveUserFromRoles(), RemoveUsersFromRole(), and RemoveUsersFromRoles() | Allow
you to remove a user from a role. You can perform this operation on
multiple users at once or remove a user from multiple roles at once,
depending on which method you use. |
IsUserInRole() | Checks whether a user is part of a specific role. |
GetRolesForUser() | Retrieves all the roles for a specific user. |
GetUsersInRole() | Retrieves all the users who are part of a specific role. |
FindUsersInRole() | Retrieves
all the users who are part of a specific role (much like
GetUsersInRole()). However, it allows you to limit the results to users
who have a specific piece of text in their user names. |
For example, you could
use the following event handler with the CreateUserWizard control to
assign a newly created user into a specific role:
Protected Sub CreateUserWizard1_CreatedUser(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles CreateUserWizard1.CreatedUser
Roles.AddUserToRole(CreateUserWizard1.UserName, "User")
End Sub
2. Restricting Access Based on Roles
Once you've created and
assigned your roles, you need to adjust your application to take the
role information into account. You can use several techniques:
You can
write authorization rules that specifically deny certain roles from
specific pages or subfolders. You can write these rules by hand by
adding the <authorization> section to your web.config file, or
you can define them with the help of the WAT by clicking the Manage
Access Rules link.
You
can use the User.IsInRole() method in your code to test whether the
user belongs to a specific role and then decide whether to allow an
action or show certain content accordingly.
You can use the LoginView control to set different content for different roles.
You already learned how to
use the first two techniques in the previous chapter. For example, you
already know how to write web.config rules that restrict a specific
group, like this:
<authorization>
<deny users="?" />
<deny roles="Guest" />
<allow users="*" />
</authorization>
These rules deny all
anonymous users and any users in the Guest role. Remember, a user may
be part of more than one role, so the order of the <deny> tags
matters. The first rule that matches determines whether the user is
allowed or denied.
Similarly, you know how to use the User.IsInRole() method to make a programmatic authorization decision:
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
lblMessage.Text = "You have reached the secured page, "
lblMessage.Text &= User.Identity.Name & "."
If User.IsInRole("Administrator") Then
lblMessage.Text &= "<br /><br />Congratulations:"
lblMessage.Text &= "you are an administrator."
End If
End Sub
The only remaining technique to consider is the LoginView control.
3. The LoginView Control
The simplest way to use the
LoginView is to show separate content for authenticated and anonymous
users. To use this design, you simply fill some content in the
<AnonymousTemplate> and <LoggedInTemplate> sections of the
control. Here's an example:
<asp:LoginView ID="LoginView1" runat="server">
<AnonymousTemplate>
<h1>You are anonymous</h1>
Why don't you <a href="Login.aspx">log in</a>?
</AnonymousTemplate>
<LoggedInTemplate>
<h1>You are logged in</h1>
<p>You are now ready to see this super-secret content.</p>
</LoggedInTemplate>
</asp:LoginView>
Figure 3 shows the two ways this control can appear, depending on whether the user is currently logged in.
The LoginView also supports
one other tag—the RoleGroups tag. Inside the RoleGroups tag, you add
one or more RoleGroup controls. Each role group is specifically mapped
to one or more roles. In other words, when you use the RoleGroups
template, you can show different content for authenticated users,
depending to which role they belong.
Here's an example:
<asp:LoginView ID="LoginView1" runat="server">
<AnonymousTemplate>
<h1>You are anonymous</h1>
Why don't you <a href="Login.aspx">log in</a>?
</AnonymousTemplate>
<RoleGroups>
<asp:RoleGroup Roles="User, Guest">
<ContentTemplate>
<p>If you can see this, you are a member of the
User or Guest roles.</p>
</ContentTemplate>
</asp:RoleGroup>
<asp:RoleGroup Roles="Administrator">
<ContentTemplate>
<p>Congratulations, you are an administrator.</p>
</ContentTemplate>
</asp:RoleGroup>
</RoleGroups>
</asp:LoginView>
Remember, a user can belong
to more than one role. However, only one template can display at a
time. When matching the role to a RoleGroup, the LoginView control goes
through the RoleGroup tags in order and uses the first match. If it
can't find a match, it uses the ordinary <LoggedInTemplate>.
The LoginView is a
fairly powerful control. It gives you an effective way to separate
secure content from ordinary content declaratively—that is, without
writing custom code to hide and show labels. This approach is clearer,
more concise, and less error prone.