The Role Provider

The Role provider is used for determining user authorization. It performs a fairly simple function: maintain which users belong to which Roles. One really key thing to remember is that the Role provider can function independently of (and even without) the Membership provider. This means that the user names used in conjunction with the Role provider don't have to match the user names used for Membership. Obviously it is in your best interest to allow them to match, but it is helpful for the custom RoleProvider programmer to know that you don't need access to the Membership database to create a Role provider. This section of the chapter introduces you to the RoleProvider abstract base class, shows you how to create your own Role schema, and then shows you how to create your own custom RoleProvider.

Introduction to the RoleProvider Base Class

The RoleProvider base class is a fairly straightforward class. By inheriting from that class and overriding its implementation with your own, you can allow the user role membership data to be stored anywhere you like. In the example discussed in this section, I'm using an XML file on the web server. Tables 29.3 and 29.4 give you a list of the properties and methods of the RoleProvider class that you will be overriding to create your own implementation.

Table 29.3. RoleProvider Properties




The only required property for a RoleProviderused to distinguish between multiple applications managed by the same provider

Table 29.4. RoleProvider Methods




Adds a list of users to a list of Roles


Creates a new Role in the data store


Deletes a Role in the data store


Returns an array of user names (Strings) where the user name matches the one supplied within the supplied Role name


Gets a list of all Roles in the data store


Gets a list of all the Roles to which a given user belongs


Indicates whether the user (either current or supplied by parameter) is in a given role


Removes a list of users from a list of roles


Indicates whether a given role name exists in the underlying data store

Implementing a Role Schema

As with the Membership schema, the data you need to maintain in your custom provider implementation is dictated by the methods exposed by the provider, and the classes utilized by that provider. The Role provider has fewer rules that need to be followed than the Membership provider, so there is more flexibility with how you store the underlying data. For example, the Membership provider made extensive use of the MembershipUser and MembershipUserCollection classes, and as such the properties of those classes dictated the schema of the stored data.

The RoleProvider interface consists mainly of passing strings and arrays of strings, and returning strings, arrays of strings, and Boolean values indicating membership in Roles. This makes the typed dataset fairly straightforward. You'll need a table to store the list of Roles, and then you'll need a table to store the list of users that belong to each role. Because all Role membership checking is done on the user's name or ID (the string UserName property in the Membership provider, also the UserName property used by the IPrincipal interface), you only need to store the user name in the detail table, as illustrated in Figure 29.2.

Figure 29.2. The RoleDataSet typed dataset.

Creating a Custom Role Provider

The code for the RoleProvider is fairly straightforward. After you add the RoleDataSet to the XMLProviders project, you can then add the RoleProvider class shown in Listing 29.2. The main thing to keep in mind when looking at this class is that the ultimate reason for the Role provider is to simply determine the roles to which each user belongs, and nothing more. Often the hardest part about creating custom providers is avoiding the pitfall of trying to make them do more work than they are responsible for.

Listing 29.2. The XML RoleProvider Class

using System; using System.Data; using System.IO; using System.Configuration; using System.Web; using System.Collections.Generic; using System.Text; using System.Web.Security; namespace SAMS.CustomProviders.XML { class RoleProvider : System.Web.Security.RoleProvider {   private string name;   private string roleFile;   private string applicationName;   private RoleDataSet roleData;   public override string Description   {     get { return "XML File-Based ASP.NET 2.0 Role Provider"; }   }   private void InitializeData()   {     roleData = new RoleDataSet();     if (File.Exists(roleFile))       roleData.ReadXml(roleFile);   }   private void SaveData()   {     roleData.AcceptChanges();     roleData.WriteXml(roleFile);   } public override void Initialize(string name,   System.Collections.Specialized.NameValueCollection config) {     try     { = name;       ApplicationName = config["applicationName"];       roleFile =        ConfigurationManager.ConnectionStrings[          config["connectionStringName"]].ConnectionString;       InitializeData();     }     catch (Exception e)     {       System.Diagnostics.Debug.WriteLine(e.ToString());     } } public override string Name { get { return name; } } public override void AddUsersToRoles(string[] usernames, string[] roleNames) {   foreach (string userName in usernames)   {     foreach (string roleName in roleNames) {         int roleId = ((RoleDataSet.RolesRow)           roleData.Roles.Select("RoleName='" + roleName +         RoleDataSet.UsersInRolesRow newRow =           roleData.UsersInRoles.NewUsersInRolesRow();         newRow.UserId = userName;         newRow.RoleId = roleId;         roleData.UsersInRoles.AddUsersInRolesRow(newRow);         SaveData();     } } } public override string ApplicationName {  get { return applicationName; }  set  {     applicationName = value;  } } public override void CreateRole(string roleName) {   RoleDataSet.RolesRow newRole = roleData.Roles.NewRolesRow();   newRole.RoleName = roleName;   newRole.ApplicationId = applicationName;   newRole.Description = roleName;   roleData.Roles.AddRolesRow(newRole);   roleData.AcceptChanges();   SaveData(); } public override bool DeleteRole(string roleName, bool throwOnPopulatedRole) {   RoleDataSet.RolesRow delRole = (RoleDataSet.RolesRow)     roleData.Roles.Select("RoleName='" + roleName + "'")[0];   DataRow[] users = roleData.UsersInRoles.Select("RoleCannot delete a role to which users are assigned.");   else   {     foreach (DataRow userInRole in users)     {        userInRole.Delete();     }     delRole.Delete();     roleData.AcceptChanges();     SaveData();     return true;   } } public override string[] FindUsersInRole(string roleName, string usernameToMatch) {   List<string> al = new List<string>();   RoleDataSet.UsersInRolesRow[] users =   (RoleDataSet.UsersInRolesRow[])roleData.Roles.Select( "RoleName = '" + roleName + "'");   foreach (RoleDataSet.UsersInRolesRow user in users)   {     if (user.UserId.ToUpper() == usernameToMatch.ToUpper())       al.Add(user.UserId);     }     return al.ToArray(); } public override string[] GetAllRoles() {   List<string> al = new List<string>();   foreach (RoleDataSet.RolesRow role in    (RoleDataSet.RolesRow[])      roleData.Roles.Select("ApplicationId='" + applicationName + "'"))   {    al.Add(role.RoleName);   }   return al.ToArray(); } public override string[] GetRolesForUser(string username) {   List<int> roleIds = new List<int>();   RoleDataSet.UsersInRolesRow[] users =    (RoleDataSet.UsersInRolesRow[])      roleData.UsersInRoles.Select("UserId = '" + username + "'");   foreach (RoleDataSet.UsersInRolesRow user in users)   roleIds.Add(user.RoleId);   List<string> roleNames = new List<string>();   foreach (int roleId in roleIds)   {     RoleDataSet.RolesRow theRow =      (RoleDataSet.RolesRow)roleData.Roles.Select("RoleRoleRoleName='" + roleName + "' AND ApplicationsId='" + applicationName + " ' ");   if (rows == null)     return -1;   if (rows.Length == 0)     return -1;   return ((RoleDataSet.RolesRow)rows[0]).RoleId; } public override bool IsUserInRole(string username, string roleName) {     int roleId = GetRoleId(roleName);     RoleDataSet.UsersInRolesRow[] users =      (RoleDataSet.UsersInRolesRow[])        roleData.UsersInRoles.Select("RoleUserId='" + userId +             "' AND Roletitle-IDADYOZL">Configuring and Installing the Role Provider 

The configuration and installation of the Role provider follows the same rules as the Membership provider. If you want your provider to be shared among more than one application on a server, you should probably install the provider into the GAC so that you don't have to have multiple copies of your provider scattered throughout a server.

To configure the Role provider, you use the <roleManager> Web.config element that you were introduced to in Chapter 28. A sample <roleManager> element designed to work with the code in this chapter is shown in the following code:

<roleManager defaultProvider="xmlRoles" enabled="true" cacheRolesInCookie="true"     cookieName=".ASPROLES" cookieTimeout="30" cookiePath="/" cookieRequireSSL="false"     cookieSlidingExpiration="true" cookieProtection="All">     <providers>       <add name="xmlRoles"         type="SAMS.CustomProviders.XML.RoleProvider"         connectionStringName="roleProvider"         applicationName="CustomProviderDemo"/> </providers> </roleManager> 

The connectionStringName attribute points to the following connection string stored in the <connectionStrings> element, which is just the physical location of the XML file:

<add name="roleProvider"    connectionString="D:\SAMS\C# Unleashed 2005\Chapters\29\Code\Data\Roles.XML"/> 

Microsoft Visual C# 2005 Unleashed
Microsoft Visual C# 2005 Unleashed
ISBN: 0672327767
EAN: 2147483647
Year: 2004
Pages: 298 © 2008-2017.
If you may any questions please contact us: