ONDotNet.com    
 Published on ONDotNet.com (http://www.ondotnet.com/)
 See this if you're having trouble printing code examples


ASP.NET Forms Security, Part 2

by Jesse Liberty
06/28/2004

In my previous column, I showed how to add web form security to your ASP.NET 2.0 application, and how to add users. In this follow up, I'll demonstrate how easy it is to create and manage roles.

Roles are essentially groups of users with specific permissions. For example, you might create roles such as Managers, Users, Administrators, Guests, and so forth. Users are assigned to one or more roles, and based on their membership in those roles, each user will have access to the appropriate parts of your application. Within any given page, the user may see different data or different controls based on the role to which the user belongs.

To illustrate this, we'll recreate the example program from the previous column, but build on it to add roles and role management.

Implementing Roles

This time, just to see another way to do things, create a new web project before you create the virtual directory. Name your new project "SecurityRoles."

Open IIS manager and create a virtual directory that points to the directory with the default.aspx file for your new application. Once the virtual directory is created, highlight it and click Properties. In the Properties window, click on the ASP.NET tab, and then click Edit Configuration. Click on the Authentication Tab, set the Authentication Mode to Forms, and click Role Management Enabled, as shown in Figure 1.


Figure 1.

If you return to the directory you created, you'll find that a web.config file has been created for you, with a configuration section in which the authentication mode is set to Forms.

<?xml version="1.0" encoding="utf-8"?>
<?configuration?>
  <?system.web?>
    <?authentication mode="Forms" /?>
    <?roleManager enabled="true" /?>
  <?/system.web?>
<?/configuration?>

You can, of course, create and edit this file by hand, if you prefer.

Add the existing pages from the previous article. Begin by copying the .aspx and aspx.cs files from the earlier project into your new directory, using Windows Explorer. Once the files are physically copied, right-click on the new project in the Solution Explorer and choose Add Existing Item. Add the .aspx files as shown in Figure 2 (the .cs files will come along automatically).


Figure 2.

Related Reading

Programming ASP.NET
By Jesse Liberty, Dan Hurwitz

Once you've added these files to your new project, modify the default page by adding two hyperlinks, one with the text Add User and a second with the text ManageRoles. Set the first link to redirect the user to the AddUser page you imported. Be sure to set the ContinueDesitnationPageURL on the AddUser page to the default page, so that you return to the default page after adding each user.

Set the default page as the start page for the project. Run the application, and navigate to the AddUser page, where you will add a few test user accounts.

The ManageRoles link on the default page will navigate to a new page you'll create named ManageRoles.aspx. To create the ManageRoles page, start with the example provided in the MSDN documentation for the May Community Preview.*

Copy the provided sample code into your ManageRoles page. Now you'll make a few changes. Put the HTML in the ManageRoles.aspx file and the code (without the script tags) into ManageRoles.aspx.cs (just delete the script and end script tags).

Once the code is in place, go to the HTML in the .aspx page and find the column with the asp:Button whose ID is AddUsersButton. Replace that td element and its contents with the following HTML:

<td valign="top" visible="false">
  <table>
    <tr>
      <td>
        <asp:Button Text="Add User(s) to Role" id="btnAddUsersToRole"
        runat="server" OnClick="AddUsers_OnClick" />
      </td>            
    </tr>
    <tr>
      <td>          
        <asp:Button Text="Create new Role" id="btnCreateRole"
         runat="server" OnClick="CreateRole_OnClick" 
         Width="170px" Height="24px" />
      </td>
    </tr>
    <tr>
      <td>
        <asp:Panel ID="pnlCreateRole" Runat="server" Width="259px" 
          Height="79px" Visible="False" BackColor="#E0E0E0">
          <br />
            
          <asp:Label ID="Label2" Runat="server" 
           Text="New Role:" Width="72px" Height="19px"/>
          <asp:TextBox ID="txtNewRole" Runat="server"/> <br />
            <br />
                     
                    
          <asp:Button ID="btnAddRole" Runat="server" Text="Add"
           OnClick="btnAddRole_Click" Width="64px" Height="24px" /><br />
        </asp:Panel>
      </td>
    </tr>
  </table>
</td>

This replacement HTML creates a table within the cell, in which you have added the button that was in the sample (Add User(s) to Role) and a new button (Create new Role) as well as a panel. In the panel are a label (New Role), a text box, and a button (Add). That panel will be set to invisible until you click the Create New Role button. When the user adds a role to the text box and clicks Add, the role will be added and the panel closed. You'll need an event handler for the Create New Role button:
void CreateRole_OnClick(object sender, EventArgs e)
{
  pnlCreateRole.Visible = true;
}

The heart of the work is done in the event handler for the Add button within the panel. Assuming there is a text, you check to ensure that the role does not already exist, and then you create the new role with the static method CreateRole:
void btnAddRole_Click(object sender, EventArgs e)
{
  // make sure you have some text in the name of hte role
  if (txtNewRole.Text.Length > 0)
  {
    string newRole = txtNewRole.Text;

    // if the role does not already exist, add it
    // rebind the RolesListBox to show the new role
    if (Roles.RoleExists(newRole) == false)
    {
      Roles.CreateRole(newRole);


You then get all the roles again and rebind the list box to show the new role.
rolesArray = Roles.GetAllRoles();
      RolesListBox.DataSource = rolesArray;
      RolesListBox.DataBind();

Finally, you "close" the panel.
pnlCreateRole.Visible = false;
}

When you open the form, the panel is invisible. Clicking on a role will display all of the users in that role, as shown in Figure 3.


Figure 3.

Clicking on Create New Role makes the panel visible, as shown in Figure 4.


Figure 4.

Testing Roles

To test the use of roles, you'll make some changes to the default page. Click on the LoginView, open the Common Tasks window, and click on Edit RoleGroups (see Figure 5).


Figure 5.

Add a few (but not all) of the roles you created earlier (see Figure 6).


Figure 6.

Switch to HTML and see the effect; a new section has been added within the LoginView control.

<asp:LoginView ID="LoginView1" Runat="server">
  <RoleGroups>
    <asp:RoleGroup Roles="User"></asp:RoleGroup>
    <asp:RoleGroup Roles="Manager"></asp:RoleGroup>
    <asp:RoleGroup Roles="Guest"></asp:RoleGroup>
  </RoleGroups>
  <LoggedInTemplate>
    Welcome
    <asp:LoginName ID="LoginName1" Runat="server" />. 
      Thank you for logging in.
  </LoggedInTemplate>
  <AnonymousTemplate>
    You have not yet logged in. Please click Login to do so now.
  </AnonymousTemplate>
</asp:LoginView>
Add more lines for the other groups you've created, and then within the RoleGroup elements, feel free to add contentTemplate elements, as shown below
<asp:LoginView ID="LoginView1" Runat="server">
    <RoleGroups>
        <asp:RoleGroup Roles="User">
            <ContentTemplate>
                Welcome  
                <asp:LoginName ID="LoginName2" Runat="server" />
                 You are logged in as a user.
            </ContentTemplate>
        </asp:RoleGroup>
        <asp:RoleGroup Roles="Administrator">
            <ContentTemplate>
                <h3>Administrative tools here</h3>
            </ContentTemplate>
        </asp:RoleGroup>
        <asp:RoleGroup Roles="Manager">
            <ContentTemplate>
                Manager tools go here
            </ContentTemplate>
        </asp:RoleGroup>
        <asp:RoleGroup Roles="Guest">
            <ContentTemplate>
                Welcome guest
            </ContentTemplate>
        </asp:RoleGroup>
    </RoleGroups>
    <LoggedInTemplate>
        Welcome
        <asp:LoginName ID="LoginName1" Runat="server" />. Thank you for logging in.
    </LoggedInTemplate>
    <AnonymousTemplate>
        You have not yet logged in. Please click Login to do so now.
    </AnonymousTemplate>
</asp:LoginView>

If you examine this closely, you'll see that within each RoleGroup you've placed a ContentTemplate that describes what content should be displayed when members of that role group log in. If you create a new user and do not assign that user to a role group, that user will see the content in the LoggedInTemplate.

For security purposes, you can of course restrict pages to people in a particular role. You can test if the logged in user is in a particular role using the User.IsInRole method:

bool isManager = User.IsInRole("Manager");

and take action accordingly. You can restrict access to pages based on roles by adding an authorization section to a web.config file (which can be placed in a subdirectory to control access to all files in that subdirectory and all of its subdirectories, and you can use the location element to control access to specific files.

The web.config file might look something like this:

<authorization>
  <deny users='?' />
  <allow roles='Manager' />
  <deny users='*' />
</authorization>

The first line (deny users = '?') prohibits access to anyone who is not logged in. The second line (allow roles='Manager') allows access to anyone in the Manager role, and the final line (deny users='*') disallows anyone, but is overridden by the allow roles.

[*] If the link does not work for you, please try copying the address into your MSDN Library, or just look up the AddUsersToRole method of the Roles class. If all else fails, you can download the complete (and fully modified) source code for this column from my web site. Click on Books and then on Articles and Publications.

Jesse Liberty is a senior program manager for Microsoft Silverlight where he is responsible for the creation of tutorials, videos and other content to facilitate the learning and use of Silverlight. Jesse is well known in the industry in part because of his many bestselling books, including O'Reilly Media's Programming .NET 3.5, Programming C# 3.0, Learning ASP.NET with AJAX and the soon to be published Programming Silverlight.


Return to ONDotnet.com

Copyright © 2009 O'Reilly Media, Inc.