我的MVC应用程序在单个页面请求期间在多个位置使用用户角色。我的问题是默认的SqlRoleProvider是否在页面请求的生命周期中缓存当前用户的角色?
例如,我在Controller方法的属性中使用Roles:
[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)
因此将使用您为应用程序选择的任何角色提供程序(默认或自定义)。
答案 0 :(得分:6)
如果在ASP.NET或ASP.NET MVC应用程序中使用RoleProvider
,则HttpContext.User
将引用RolePrincipal
,它会在请求的生命周期内执行缓存角色。 / p>
但是,在使用ASP.NET角色的WCF服务中:
<behavior ...>
<serviceAuthorization principalPermissionMode ="UseAspNetRoles"
roleProviderName ="MyRoleProvider" />
</behavior>
这不是真的:而HttpContext.User
将引用内部类System.ServiceModel.Security.RoleProviderPrincipal
,它不会缓存角色:而是始终调用RoleProvider.IsUserInRole
。
开箱即用的RoleProviders不进行任何缓存,因此可能导致重复连接到底层数据存储。对我来说这似乎是一个缺陷:在首次访问时缓存角色很容易。
是编写从默认角色继承者继承的自定义角色提供程序的最佳解决方案,并覆盖方法以获取角色一次并在请求持续时间内缓存它们?
对于ASP.NET或ASP.NET MVC不是必需的,但可以为WCF设想。请求持续时间的缓存可能会使用HttpContext.Items
,因此会引入HttpContext
存在的依赖关系,但除了使单元测试更难之外,这不一定是个问题。
这可以通过Authorize属性和我自己的代码都使用缓存角色的方式完成吗?
如果您在web.config中配置自定义RoleProvider
,则无需执行任何操作,Authorize
属性将使用它。