当我实现RoleProvider类并调用Roles.IsUserInRole(string username,string roleName)时,代码执行首先转到方法’GetRolesForUser(string username)’.为什么是这样?当我只是寻找该用户是否属于一个角色的单一值时,我不想迭代所有角色.这是.NET角色提供程序类的限制,还是有一些我可以做的更多的控制代码的执行?
if (Roles.IsUserInRole(CurrentUser.UserName,"Teacher")) {
这是IsUserInRole的实现
public override bool IsUserInRole(string username,string roleName) { return true; }
但代码GetRolesForUser始终首先实现:
public override string[] GetRolesForUser(string username) { string[] roles = GetAllRoles(); List<string> userRoles = new List<string>(); foreach (string role in roles) { if (IsUserInRole(username,role)) { userRoles.Add(role); } } return userRoles.ToArray(); }
解决方法
有一个层面的Microsoft角色提供程序解决方案,可以缓存用户的角色在cookie中,因此不需要调用提供程序的GetRolesForUser方法.我相信cookie缓存是Roles类的一部分,所以只要从RoleProvider基类实现,它应该是兼容的.值得一看的反思中的代码来了解MS如何实现自己的抽象类,以及静态助手类(Roles and Membership)
尝试在配置文件中的roleManager元素中添加cacheRolesInCookie =“true”,并查看流程是否发生更改.
由于您使用自己的RoleProvider实现,您还可以覆盖IsUserInRole方法,并提供自己的检查用户是否在角色中的实现.
更新:这个代码块在Roles.IsUserInRole方法中被调用:
IPrincipal currentUser = GetCurrentUser(); if (((currentUser != null) && (currentUser is RolePrincipal)) && ((((RolePrincipal) currentUser).ProviderName == Provider.Name) && StringUtil.EqualsIgnoreCase(username,currentUser.Identity.Name))) { flag = currentUser.IsInRole(roleName); } else { flag = Provider.IsUserInRole(username,roleName); }
其他块是什么叫做您的自定义提供者的IsUserInRole方法.
因此,您的用户的角色尚未添加到Principal对象.如果你还没有走到这一步,好的.如果没有,请确保你这样做.它将确保每次您调用Roles.IsUserInRole或User.IsInRole时,这些函数将使用用户角色的内存中缓存(一旦加载),而不必每次都进入数据库. (尽管基础角色提供程序和角色管理器类应该为您照顾.)
您可以验证角色提供程序的配置文件设置吗?另外,你使用什么版本的.net?您是手动管理登录过程还是使用.net登录控制?您是否实施了一个自定义角色类?还是使用System.Web.Security.Roles?