9

我的 MVC 应用程序在单个页面请求期间在多个位置使用用户角色。我的问题是默认 SqlRoleProvider 是否在页面请求的生命周期内缓存当前用户的角色?

例如,我在 Controller 方法的属性中使用角色:

[Authorize(Roles = "Admin")]

和自定义代码

if (user.IsInRole(MembershipRole.Admin))
{
     // Do something
}
else if (user.IsInRole(MembershipRole.Printer))
{
     // Do something else
}

如果角色提供者不缓存角色,最好的解决方案是编写一个继承自默认角色提供者的自定义角色提供者,并覆盖获取角色一次并在请求期间缓存它们的方法?这可以通过 Authorize 属性和我自己的代码都使用缓存角色的方式来完成吗?

(如果您想知道,我不想使用 cacheRolesInCookie web.config 选项来缓存 cookie 中的角色)。

在此先感谢您的任何建议。

[编辑以包含由乔的回答触发的详细信息]

我反编译了 System.Web.Mvc.AuthorizeAttribute 并且 AuthorizeCore 方法为要检查的每个角色调用以下方法:

httpContext.User.IsInRole

然后查看 System.Web.Security.RolePrincipal (即上面的“用户”),下面的两种方法确实使用了用户角色的缓存副本(如果为空,则填充缓存):

public string[] GetRoles()
public bool IsInRole(string role)

缓存存储为 User 上的一个字段,因此它的生命周期是在请求期间。

这些方法使用以下方法查找角色:

Roles.Providers[this._ProviderName].GetRolesForUser(this.Identity.Name)

所以将使用您为应用程序选择的任何角色提供程序(默认或自定义)。

4

1 回答 1

7

如果您RoleProvider在 ASP.NET 或 ASP.NET MVC 应用程序中使用 a,HttpContext.User则将引用RolePrincipal在请求的生命周期内缓存角色的 a。

但是,在使用 ASP.NET 角色的 WCF 服务中:

<behavior ...>
    <serviceAuthorization principalPermissionMode ="UseAspNetRoles"
                     roleProviderName ="MyRoleProvider" />
</behavior>

这不是真的:而是HttpContext.User会引用System.ServiceModel.Security.RoleProviderPrincipal不缓存角色的内部类:相反,它总是调用RoleProvider.IsUserInRole.

开箱即用的 RoleProvider 不进行任何缓存,因此这可能会导致与底层数据存储的重复连接。这对我来说似乎是一个缺陷:在第一次访问时缓存角色会很容易。

是编写从默认角色提供者继承的自定义角色提供者的最佳解决方案,并覆盖获取角色一次并在请求持续时间内缓存它们的方法吗?

对于 ASP.NET 或 ASP.NET MVC 不是必需的,但可以为 WCF 设想。Request 持续时间的缓存可能会使用HttpContext.Items,因此会引入对 的存在的依赖HttpContext,但这不一定是问题,除非使单元测试更难。

这可以通过 Authorize 属性和我自己的代码都使用缓存角色的方式来完成吗?

如果您RoleProvider在 web.config 中配置您的自定义,则您无需再做任何事情,该Authorize属性将使用它。

于 2012-12-12T14:55:17.240 回答