[Authorize(Roles = "Admin")]
if (user.IsInRole(MembershipRole.Admin)) { // Do something } else if (user.IsInRole(MembershipRole.Printer)) { // Do something else }
如果角色提供程序不缓存角色,是编写从默认角色继承的自定义角色提供程序的最佳解决方案,并覆盖方法以获取角色一次并在请求持续时间内缓存它们?这可以通过Authorize属性和我自己的代码都将使用缓存的角色来完成吗?
(如果您想知道,我不想使用cacheRolesInCookie web.config选项来缓存cookie中的角色).
在此先感谢您的任何建议.
[编辑以包含Joe的答案触发的详细信息]
我反编译了System.Web.Mvc.AuthorizeAttribute,AuthorizeCore方法为每个要检查的角色调用以下方法:
httpContext.User.IsInRole
然后窥视System.Web.Security.RolePrincipal(上面是“User”),下面的方法确实使用了用户角色的缓存副本(或者如果为空则填充缓存):
public string[] GetRoles() public bool IsInRole(string role)
缓存作为字段存储在User上,因此其生命周期是在请求期间.
Roles.Providers[this._ProviderName].GetRolesForUser(this.Identity.Name)
因此将使用您为应用程序选择的任何角色提供程序(默认或自定义).
解决方法
但是,在使用ASP.NET角色的WCF服务中:
<behavior ...> <serviceAuthorization principalPermissionMode ="UseAspNetRoles" roleProviderName ="MyRoleProvider" /> </behavior>
事实并非如此:相反,HttpContext.User将引用内部类System.ServiceModel.Security.RoleProviderPrincipal,它不会缓存角色:而是始终调用RoleProvider.IsUserInRole.
开箱即用的RoleProviders不进行任何缓存,因此可能导致重复连接到底层数据存储.对我来说这似乎是一个缺陷:在首次访问时缓存角色很容易.
is the best solution to write a custom Role Provider that inherits from the default one,and override the methods to get the Roles once and cache them for the Request duration?
对于ASP.NET或ASP.NET MVC不是必需的,但可以为WCF设想.请求持续时间的缓存可能会使用HttpContext.Items,因此会引入对HttpContext存在的依赖,但这不一定是一个问题,除了使单元测试更难.
Can this be done in a way that both the Authorize attribute and my own code will make use of the cached roles?
如果在web.config中配置自定义RoleProvider,则无需执行任何操作,以便Authorize属性将使用它.