实现角色提供程序比实现成员资格提供程序容易,因为用于管理角色的结构比较简单。没有什么新概念,只需要调用 RoleStore 类的相应方法创建角色、删除角色、将用户分配到角色以及从角色中删除用户即可。
角色提供程序的完整接口如下:
public class XmlRoleProvider : RoleProvider
{
public override void Initialize(string name, NameValueCollection config)
public override string ApplicationName { get; set; }
public override void CreateRole(string roleName)
public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
public override bool RoleExists(string roleName)
public override void AddUsersToRoles(string[] usernames, string[] roleNames)
public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
public override string[] GetAllRoles()
public override string[] GetRolesForUser(string username)
public override string[] GetUsersInRole(string roleName)
public override bool IsUserInRole(string username, string roleName)
public override string[] FindUsersInRole(string roleName, string usernameToMatch)
}
这个类从 RoleProvider 继承而来。再次覆盖初始化自定义属性的 Initialize 方法,不过这次简单很多,因为角色提供程序只支持一小部分属性。基类提供的唯一属性就是 ApplicationName,其他的就由你来决定了。
public override void Initialize(string name, NameValueCollection config)
{
if (config == null)
{
throw new ArgumentException("config");
}
if (string.IsNullOrEmpty(name))
{
name = "XmlRoleProvider";
}
if (string.IsNullOrEmpty(config["description"]))
{
config.Remove("description");
config.Add("description", "XML Role Provider");
}
base.Initialize(name, config);
applicationName = "DefaultApp";
foreach (string key in config.Keys)
{
if (key.ToLower().Equals("applicationname"))
{
applicationName = config[key];
}
else if (key.ToLower().Equals("filename"))
{
fileName = config[key];
}
}
}
再次检查名称和描述配置参数,如果它们没有经过配置,就使用默认值初始化。不要忘记调用基类的 Initialize,否则,由基类托管的默认配置值就不会被初始化。FileName 属性指定了存储角色信息的 XML 文件名称。
接着,这个类提供了一些方法来管理角色,需要访问底层的 RoleStore 方法。例如,创建一个角色:
public override void CreateRole(string roleName)
{
SimpleRole newRole = new SimpleRole();
newRole.RoleName = roleName;
newRole.AssignedUsers = new StringCollection();
CurrentStore.Roles.Add(newRole);
currentStore.Save();
}
RoleExists() 确认传入的角色名称是否在列表中:
public override bool RoleExists(string roleName)
{
try
{
return CurrentStore.GetRole(roleName) != null;
}
catch
{
throw;
}
}
DeleteRole() 则试图删除底层存储的角色:
public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
{
try
{
SimpleRole role = CurrentStore.GetRole(roleName);
if (role == null)
{
return false;
}
else
{
CurrentStore.Roles.Remove(role);
CurrentStore.Save();
return true;
}
}
catch
{
throw;
}
}
AddUsersToRoles() 将用户添加到一个角色中。这个方法相对复杂一些。首先遍历角色数组,分别获取每一个角色实例,比较该角色的用户列表和传入的用户列表进行用户的添加:
public override void AddUsersToRoles(string[] usernames, string[] roleNames)
{
try
{
foreach (string roleName in roleNames)
{
SimpleRole role = CurrentStore.GetRole(roleName);
if (role != null)
{
foreach (string username in usernames)
{
if (!role.AssignedUsers.Contains(username))
{
role.AssignedUsers.Add(username);
}
}
}
}
CurrentStore.Save();
}
catch
{
throw;
}
}
RemoveUsersFromRoles() 的功能则和上面相反:
public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
{
try
{
foreach (string roleName in roleNames)
{
SimpleRole role = CurrentStore.GetRole(roleName);
if (role!=null)
{
foreach (string username in usernames)
{
if (role.AssignedUsers.Contains(username))
{
role.AssignedUsers.Remove(username);
}
}
}
}
CurrentStore.Save();
}
catch
{
throw;
}
}
自定义角色提供程序其余的方法实现起来就非常简单了,大多数情况下,这些方法只是遍历存储中的角色并返回一些信息。大多数情况下是用户名或者角色名的字符串数组。如下所示:
public override string[] GetAllRoles()
{
try
{
return CurrentStore.Roles.Select(p => p.RoleName).ToArray();
}
catch
{
throw;
}
}
public override string[] GetRolesForUser(string username)
{
try
{
return CurrentStore.GetRolesForUser(username).Select(p => p.RoleName).ToArray();
}
catch
{
throw;
}
}
public override string[] GetUsersInRole(string roleName)
{
try
{
return CurrentStore.GetUsersInRole(roleName);
}
catch
{
throw;
}
}
public override bool IsUserInRole(string username, string roleName)
{
try
{
SimpleRole role = CurrentStore.GetRole(roleName);
if (role != null)
{
return role.AssignedUsers.Contains(username);
}
else
{
throw new ProviderException("Role does not exist!");
}
}
catch
{
throw;
}
}
FindUsersInRole() 试着用 roleName 参数通过模式匹配来查找用户。SQL 成员资格提供程序使用 % 符号来进行模式匹配,但是正则表达式不把 % 符号作为占位符,因此要用一个正则表达式可识别的表示来替换它,即 \w* 。
public override string[] FindUsersInRole(string roleName, string usernameToMatch)
{
try
{
SimpleRole role = CurrentStore.GetRole(roleName);
if (role != null)
{
List<string> results = new List<string>();
Regex expression = new Regex(usernameToMatch.Replace("%", @"\w*"));
foreach (string userName in role.AssignedUsers)
{
if (expression.IsMatch(userName))
{
results.Add(userName);
}
}
return results.ToArray();
}
else
{
throw new ProviderException("Role does not exist!");
}
}
catch
{
throw;
}
}
通常,知道如何实现一个提供程序之后,就会知道如何实现另一个提供程序。这个流程没有什么新的概念,只是需要一些代码量和仔细的工作。