ASP.NET 自定义成员资格提供程序 Part.3(实现提供程序类:XmlRoleProvider)

       实现角色提供程序比实现成员资格提供程序容易,因为用于管理角色的结构比较简单。没有什么新概念,只需要调用 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;
    }
}

 

       通常,知道如何实现一个提供程序之后,就会知道如何实现另一个提供程序。这个流程没有什么新的概念,只是需要一些代码量和仔细的工作。

posted on 2013-05-03 17:01  SkySoot  阅读(325)  评论(0编辑  收藏  举报

导航