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;
}
}
通常,知道如何实现一个提供程序之后,就会知道如何实现另一个提供程序。这个流程没有什么新的概念,只是需要一些代码量和仔细的工作。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架