【问题标题】:Does Role Provider cache per request?角色提供者是否缓存每个请求?
【发布时间】:2012-12-12 14:48:08
【问题描述】:

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

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

[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)

缓存作为一个字段存储在用户上,所以它的生命周期是请求的持续时间。

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

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

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

【问题讨论】:

    标签: asp.net asp.net-mvc roleprovider sqlroleprovider


    【解决方案1】:

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

    但是,在使用 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 设想。请求持续时间的缓存大概会使用HttpContext.Items,因此会引入对HttpContext 存在的依赖,但这不一定是个问题,除非使单元测试更难。

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

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

    【讨论】:

    • 感谢您的意见。 RolePrincipal 上的 MSDN 文档说,“如果 CacheRolesInCookie 为 false,则 RolePrincipal 对象总是使用角色提供者查找角色成员资格。”。当您说 RolePrincipal “在请求的生命周期内缓存角色”时,我可以问一下您是如何知道这一点的(反射、SQL 分析、文档等),因为它似乎与 MSDN 相矛盾?
    • @Steve,我通过查看实现(Lutz Reflector 或 ILSpy)以及实现自定义提供程序的经验知道这一点。这与 MSDN 并不矛盾:RolePrincipal 确实使用角色提供程序查找角色成员 - 它调用 RoleProvider.GetRolesForUser,但每次请求仅调用一次,将结果缓存在 HybridDictionary 字段中。 WCF 的 RoleProviderPrincipal 不调用 RoleProvider.GetRolesForUser,而是始终调用 RoleProvider.IsInRole 并且不实现任何角色缓存。
    • 谢谢。我遵循了您的方法并反编译了相关程序集以查看实际发生的情况。在我原来的问题中添加了一些细节以添加到您的答案中。
    猜你喜欢
    • 2015-04-11
    • 2023-03-14
    • 1970-01-01
    • 2011-02-17
    • 2014-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-08
    相关资源
    最近更新 更多