12.2. Add Roles to ASP.NET Accounts


Authentication is the process of identifying a user; authorization is the process of deciding which parts of your application that user can see and interact with. The forms-based security controls and database that comes with Visual Basic 2005 allows you to set authorization for specific users based on their being assigned to a role (such as guest, member, manager, etc). You do so in three steps: create the roles, assign permissions to each role, and then assign users to the roles. Any given user may be in more than one role (e.g., administrator and manager). The permissions you assign to each role may determine access to a page, or may change the content of a given page displayed to members of that role.

12.2.1. Create a New Application with Roles

To demonstrate how to create roles and assign users to those roles, you'll need to create a new application, ASPSecurityRoles. Begin by copying over the web site you used in the previous exercise (FormBasedSecurity), as shown in Figure 12-21.

Figure 12-21. Copy web site


Set Welcome as the Start page and run the program to make sure you can still log in. Open the WAT and click on the Security tab. In the second column (Roles), you'll see that roles are not enabled. Click on Enable Roles, as shown in Figure 12-22.

Figure 12-22. Enabling roles in WAT


Open Web.config and you'll see that the WAT has updated it to add roles management:

     <system.web>        <roleManager enabled="true" />        <authentication mode="Forms"/>        <membership defaultProvider="AspNetSqlMembershipProvider"/>        <compilation debug="true"/>     </system.web> 

Depending on how your machine is set up and which database you are using, you may or may not have the defaultProvider enTRy in your Web.config.


Once roles have been created, use the WAT to create your first Role: Manager (it is helpful to have an initial role and a user in that role so that you can have in your code a test to ensure that only Managers, for example, can create new roles or add users to roles).

What you actually call that role manager, adminstrator, tsar is entirely up to you.


Under Add/Remove users, click the Manage link and navigate to one of your users (e.g., jliberty) and click the User Is In Role box to add that user to the role, as shown in Figure 12-23.

Using the LoginView's smart tag, click on Edit Templates and edit the Logged In Template. Add three hyperlinks to the Logged In Template on the Welcome page, as shown in Figure 12-24. Set the NavigateURL to ChangePW.aspx, CreateAccount.aspx, and ManageRoles.aspx, respectively. Be sure to click on End Template Editing when you are done.

Create the ChangePW.aspx page and drag a ChangePassword control onto the page. Use the smart tag to format the ChangePassword control, as shown in Figure 12-25.

Set the ContinueDestinationPageURL property to Login.aspx, and on Login.aspx make sure the ContinueDestinationPageURL of the Login control is set to Welcome.aspx. You may also want to confirm or change the Success Text as well as the other text fields (ChangePasswordTitleText, ChangePasswordFailureText, etc.)

Figure 12-23. Adding users to roles in WAT


Figure 12-24. End Template Editing of Logged In Template


Figure 12-25. ChangePassword control


Create the ManageRoles.aspx page. This new page has a somewhat complex layout since it must display the list of roles and the list of users supported by your site, as well as which users have been assigned which roles. The page is shown in Figure 12-26, and the controls are listed in Table 12-1.

Figure 12-26. ManageRoles.aspx


Table 12-1. Controls in ManageRoles.aspx

Control name

Control type

Attributes

linkHome

Hyperlink

Inner HTML: Home PageNavigateURL= "Welcome.aspx"

Msg

Label

 

RolesListBox

ListBox

Autopostback=true

UsersListBox

ListBox

Autopostback=true

btnAddUsersToRole

Button

Add User(s) to RoleOnClick="AddUsers_OnClick"

btnCreateRole

Button

Create new RoleOnClick="CreateRole_OnClick"

pnlCreateRole

Panel

Visible="False"

Label2

Label

New Role:

txtNewRole

TextBox

 

btnAddRole

Button

Text="Add"OnClick="btnAddRole_Click"

UsersInRoleGrid

GridView

 


The UsersInRoleGrid should look like Example 12-2.

Example 12-2. UserInRoleGrid source
 <asp:GridView runat="server" CellPadding="4"                  AutoGenerateColumns="false" Gridlines="None"                 CellSpacing="0" OnRowCommand="UsersInRoleGrid_RemoveFromRole">        <HeaderStyle BackColor="navy" ForeColor="white" />        <Columns>         <asp:TemplateField HeaderText="User Name">           <ItemTemplate>            <%# Container.DataItem.ToString( ) %>           </ItemTemplate>         </asp:TemplateField>         <asp:ButtonField Text="Remove From Role" ButtonType="Link" />        </Columns> </asp:GridView> 

All of these controls should be laid out in a table, with the text inserted into columns as well. The finished page is shown in Example 12-3.

Example 12-3. Manage Role Page source
 <%@ Page Language="VB" AutoEventWireup="false" CodeFile="ManageRoles.aspx.vb" Inherits="ManageRoles_aspx" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/ xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server">    <title>Manage Roles</title> </head> <body>    <form  runat="server">   <h3>Role Membership     <asp:HyperLink  Runat="server" NavigateUrl="Welcome.aspx">          Home page     </asp:HyperLink>   </h3>   <asp:Label  ForeColor="maroon" runat="server" /><BR>   <table CellPadding="3" border="0">    <tr>     <td valign="top">Roles:</td>     <td valign="top" style="width: 186px">         <asp:ListBox             runat="server" Rows="8" AutoPostBack="True" />     </td>     <td valign="top">Users:</td>     <td valign="top">       <asp:ListBox  DataTextField="Username"          Rows="8" SelectionMode="Multiple" runat="server" />    </td>     <td valign="top" visible="false">         <table>         <tr>            <td>               <asp:Button Text="Add User(s) to Role"                runat="server" OnClick="AddUsers_OnClick" />            </td>         </tr>         <tr>            <td>               <asp:Button Text="Create new Role"                runat="server" OnClick="CreateRole_OnClick"               Width="170px" Height="24px" />            </td>         </tr>         <tr>         <td>        <asp:Panel  Runat="server" Width="259px"         Height="79px" Visible="False" BackColor="#E0E0E0">           <br />           &nbsp;&nbsp;           <asp:Label  Runat="server" Text="New Role:"            Width="72px" Height="19px"/>           <asp:TextBox  Runat="server"/>&nbsp;<br />           &nbsp;&nbsp;<br />           &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;           &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;           <asp:Button  Runat="server"             Text="Add" OnClick="btnAddRole_Click"             Width="64px" Height="24px" /><br />        </asp:Panel>         </td>         </tr>         </table>     </td>    </tr>    <tr>     <td valign="top">Users In Role:</td>     <td valign="top" style="width: 186px">         <asp:GridView runat="server" CellPadding="4"                          AutoGenerateColumns="false" Gridlines="None"                         CellSpacing="0"         OnRowCommand="UsersInRoleGrid_RemoveFromRole">                <HeaderStyle BackColor="navy" ForeColor="white" />                <Columns>                 <asp:TemplateField HeaderText="User Name">                   <ItemTemplate>                    <%# Container.DataItem.ToString( ) %>                   </ItemTemplate>                 </asp:TemplateField>                 <asp:ButtonField Text="Remove From Role" ButtonType="Link" />                </Columns>         </asp:GridView>      </td>    </tr>   </table>   </form> </body> </html> 

This page is not designed to be pretty, just useful. It is based on a demonstration .aspx page provided by Microsoft.


The code-behind page must implement five event handlers:

  • Page_Load

  • AddUsers_OnClick (adding users to roles)

  • UsersInRoleGrid_RemoveFromRole (removing users from roles)

  • CreateRole_OnClick (opening panel to create a new role)

  • btnAddRole_Click (adding new role)

Your class will declare three member variables:

  • A string array named rolesArray

  • A string array named usersInRole

  • An instance of MembershipUserCollection named users

The MembershipUserCollection is defined by the Framework to hold MembershipUser objects (surprise!). A MembershipUser object, in turn, is defined by the Framework to represent a single user in the membership data store (in this case, the tables created in SqlServerExpress). This class exposes information about the user such as the user's email address, and methods such as those needed to change or reset the user's password.

Here's how the code works. The first step is to override the Page_Load event handler, as shown in Example 12-4.

Example 12-4. Page_Load
 Protected Sub Page_Load( _ ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Me.Load    If User.IsInRole("Manager") = False Then       Response.Redirect("NoPrivs.aspx")    End If    Msg.Text = String.Empty    If Not IsPostBack Then       rolesArray = Roles.GetAllRoles( )       RolesListBox.DataSource = rolesArray       RolesListBox.DataBind( )       users = Membership.GetAllUsers( )       UsersListBox.DataSource = users       UsersListBox.DataBind( )    End If    If (RolesListBox.SelectedItem IsNot Nothing) Then       usersInRole = Roles.GetUsersInRole(RolesListBox.SelectedItem.Value)       UsersInRoleGrid.DataSource = usersInRole       UsersInRoleGrid.DataBind( )    End If End Sub 

First check that the current user is a manager. If he is, a redirect to an error page:

      If User.IsInRole("Manager") = False Then         Response.Redirect("NoPrivs.aspx")      End If 

If this is the first time you are displaying the page, get the rolls and bind them to the list box, then get all the users and bind that collection to the Users List Box:

        If Not IsPostBack Then           rolesArray = Roles.GetAllRoles( )           RolesListBox.DataSource = rolesArray           RolesListBox.DataBind( )           users = Membership.GetAllUsers( )           UsersListBox.DataSource = users           UsersListBox.DataBind( )        End If 

If there is a selected item in the Roles List Box, get the list of users who are in that role and bind the list to the users in Roll Grid:

        If (RolesListBox.SelectedItem IsNot Nothing) Then           usersInRole = Roles.GetUsersInRole(RolesListBox.SelectedItem.Value)           UsersInRoleGrid.DataSource = usersInRole           UsersInRoleGrid.DataBind( )        End If 

Step 2 is to implement the AddUsers_OnClick event handler, as shown in Example 12-5.

Example 12-5. AddUsers_OnClick handler
 Protected Sub AddUsers_OnClick( _ ByVal sender As Object, _ ByVal e As System.EventArgs) Handles btnAddUsersToRole.Click     '  A role must be selected     If RolesListBox.SelectedItem Is Nothing Then         Msg.Text = "Please select a role."         Exit Sub     End If     ' At least one user must be selected     If UsersListBox.SelectedItem Is Nothing Then         Msg.Text = "Please select one or more users."         Exit Sub     End If     ' Create list of users to be added to the selected role     Dim sizeOfArray As Integer = UsersListBox.GetSelectedIndices.Length     Dim newUsers(sizeOfArray - 1) As String     'For i As Integer = 0 To newusers.Length - 1     '    newusers(i) = _     '    UsersListBox.Items( _     '        UsersListBox.GetSelectedIndices( )(i)).Value     'Next     For i As Integer = 0 To newUsers.Length - 1         ' get the array of selected indices from the (multiselect) list box         Dim selectedIndices As Integer( ) = UsersListBox.GetSelectedIndices( )         ' get the selectedIndex that corresponds to the counter (i)         Dim selectedIndex As Integer = selectedIndices(i)         ' get the ListItem in the UserListBox Items collection at that offset         Dim myListItem As ListItem = UsersListBox.Items(selectedIndex)         ' get the string that is that ListItem's value property         Dim newUser As String = myListItem.Value         ' add that string to the newUsers collection of string         newUsers(i) = newUser     Next     ' Add users to the selected role     Roles.AddUsersToRole(newUsers, RolesListBox.SelectedItem.Value)     usersInRole = Roles.GetUsersInRole(RolesListBox.SelectedItem.Value)     UsersInRoleGrid.DataSource = usersInRole     UsersInRoleGrid.DataBind( ) End Sub 

First, check to make sure that a role has been selected:

     If RolesListBox.SelectedItem Is Nothing Then         Msg.Text = "Please select a role."         Exit Sub     End If 

At least one user should be selected:

     If UsersListBox.SelectedItem Is Nothing Then         Msg.Text = "Please select one or more users."         Exit Sub     End If 

Create an array to hold the users to be added:

     Dim sizeOfArray As Integer = UsersListBox.GetSelectedIndices.Length     Dim newusers(sizeOfArray - 1) As String 

Iterate through the users, retrieving each selected user's name:

     For i As Integer = 0 To newusers.Length - 1         newusers(i) = _         UsersListBox.Items( _             UsersListBox.GetSelectedIndices( )(i)).Value     Next 

This statement is pretty complicated. The best way to understand it is to rewrite it using interim variables, like this:

     For i As Integer = 0 To newUsers.Length - 1         ' get the array of selected indices from the (multiselect) list box         Dim selectedIndices As Integer( ) = UsersListBox.GetSelectedIndices( )         ' get the particular selectedIndex that corresponds to the counter (i)         Dim selectedIndex As Integer = selectedIndices(i)         ' get the ListItem in the UserListBox Items collection at that offset         Dim myListItem As ListItem = UsersListBox.Items(selectedIndex)         ' get the string that is that ListItem's value property         Dim newUser As String = myListItem.Value         ' add that string to the newUsers collection of string         newUsers(i) = newUser     Next 

The advantage of the interim variables is that you can set break points on them and see what their value is, and you can more easily document the code. The disadvantage is minimal, but many programmers (especially those from the "C" culture!) still prefer the terser version.

Next, call the static AddUsersToRole on the Roles class, passing in the array of usernames, and the role you want these users added to. Rebind the users who are in that role to the UsersInRoleGrid:

     Roles.AddUsersToRole(newUsers, RolesListBox.SelectedItem.Value)     usersInRole = Roles.GetUsersInRole(RolesListBox.SelectedItem.Value)     UsersInRoleGrid.DataSource = usersInRole     UsersInRoleGrid.DataBind( ) 

As noted earlier, step 3 is to implement UsersInRoleGrid_RemoveFromRole as shown in Example 12-6.

Example 12-6. UsersInRoleGrid_RemoveFromRole
 Protected Sub UsersInRoleGrid_RemoveFromRole( _ ByVal sender As Object, _ ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) _ Handles UsersInRoleGrid.RowCommand    ' get the user to remove    Dim index As Integer = Convert.ToInt32(e.CommandArgument)    Dim username As String = _    CType(UsersInRoleGrid.Rows(index).Cells(0).Controls(0), _        DataBoundLiteralControl).Text    ' remove the user    Roles.RemoveUserFromRole(username, RolesListBox.SelectedItem.Value)    ' Rebind the users in role to Gridview    usersInRole = Roles.GetUsersInRole(RolesListBox.SelectedItem.Value)    UsersInRoleGrid.DataSource = usersInRole    UsersInRoleGrid.DataBind( ) End Sub 

Step 4 is to add the Create Role_OnClick event handler, which makes the CreateRole panel visible, as shown in Example 12-7.

Example 12-7. CreateRole button Click event handler
 Protected Sub CreateRole_OnClick  ( _ ByVal sender As Object, _ ByVal e As System.EventArgs) Handles btnCreateRole.Click     pnlCreateRole.Visible = True End Sub 

The purpose of this is to present the panel, which contains a text box for the user to enter a new role and an Add button, as shown in Figure 12-27.

Figure 12-27. Create new role


Finally, implement the btnAddRole_Click event handler, shown in Example 12-8.

Example 12-8. AddRole button Click event handler
 Protected Sub btnAddRole_Click( _ ByVal sender As Object, _ ByVal e As System.EventArgs) Handles btnAddRole.Click     If txtNewRole.Text.Length > 0 Then         Dim newRole As String = txtNewRole.Text         ' if the role does not already exist, add it         ' rebind the roles     list box         If Roles.RoleExists(newRole) = False Then             Roles.CreateRole(newRole)             rolesArray = Roles.GetAllRoles( )             RolesListBox.DataSource = rolesArray             RolesListBox.DataBind( )         End If     End If     txtNewRole.Text = String.Empty     pnlCreateRole.Visible = False End Sub 

Check to make sure there is text in the NewRole text box, and then check to make sure the role does not exist. If it does not, create the new role using the Shared CreateRole method of the Roles class, provided by the Framework.

You do not need an instance of Roles to call CreateRole because CreateRole is Shared.


Get all the roles by calling the Shared method GetAllRoles and store the roles in the member array rolesArray, to which you bind the list box. When the role is added, the text box is cleared and the panel is made invisible.

Run the application and click on Manage Roles to add a couple of roles. Next, click on a role (to highlight it) and highlight one or more users; then click Add User(s) to Role. The results are shown in Figure 12-28.

Figure 12-28. Adding users to roles


Add each user to one or more roles.

12.2.2. Restricting Access to Pages Based on Roles

There are two ways to restrict access to a page based on membership in a Role. The first is to test if the logged-in user is in a particular role, using the User.IsInRole( ) method:

     Dim isManager as boolean  = User.IsInRole("Manager") 

You might redirect the user to an error page if the user is not in the required role. As an example, let's add code that blocks nonmanagers from linking to the Manage Roles page. To do so, add a test in the Page_Load method of ManageRoles.aspx.vb:

     Protected Sub Page_Load( _     ByVal sender As Object, _     ByVal e As System.EventArgs) Handles Me.Load         If User.IsInRole("Manager") = False Then             Response.Redirect("NoPrivs.aspx  ")         End If 

If the user is not in the role of "Manager," the user is redirected to the page NoPrivs.aspx. That page can display an error message and then allow the user to take other actions. A very simple example is shown in Figure 12-29.

Figure 12-29. NoPrivs.aspx


The code for the button (btnHome) on the NoPrivs.aspx.vb page, whose text is "Return to Welcome," is very simple and shown in Example 12-9.

Example 12-9. Return to Welcome button Click event handler
 .Protected Sub btnHome_Click( _ ByVal sender As Object, _ ByVal e As System.EventArgs) Handles btnHome.Click     Response.Redirect("Welcome.aspx") End Sub 

12.2.3. Restricting Access to a Set of Pages

You can also restrict access to a set of pages by adding an authorization section to a Web.config file. You place this file in a subdirectory to control access to all files in that subdirectory and all of its subdirectories, and you use the location element to control access to specific files:

     <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 everyone, but is overridden by the allow roles.



Programming Visual Basic 2005
Programming Visual Basic 2005
ISBN: 0596009496
EAN: 2147483647
Year: 2006
Pages: 162
Authors: Jesse Liberty

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