在何处以及如何"缓存"ASP.NET角色数据

Bre*_*ias 4 asp.net oop authentication authorization

设计选择

假定两个ASP.NET MVC授权/角色设计故事.两者都旨在最大限度地减少针对中间层或数据存储的命中:

  • 从数据库中获取"MyRoleProvider"信息后,它随后存储在AuthTicket用户数据中,这反过来意味着auth-cookie包含role-info.此外,在本文中,存储和检索此角色信息是通过完全在"MyRoleProvider"之外的独特实现来完成的.

要么...

  • 从数据库中获取"MyRoleProvider"信息后,它随后存储在会话中并从那里进行访问.更确切地说,类"MyRoleProvider"本身将在可能的情况下在内部访问(和更新)会话.

同样,上述两个故事都旨在通过"缓存"角色信息来最小化击中外部商店的延迟.两者都很好.问题是,两个设计故事选择同样有效吗?如果没有,为什么?

问题

在任何地方似乎都没有"最佳实践",其中说"你的(自定义)RoleProvider应该始终知道在哪里找到角色信息,无论是在会话,缓存,数据库等等."

此外,似乎没有任何(可靠)指导可以解释您不应该在authCookie 中的" userData "中存储哪些类型的内容.那里的文档和指导只有两点:

  1. 'userData'可以存储其他用户信息(模糊,广泛的声明).我在网上只看到一个代码示例,其中涉及存储额外的第三方身份/身份验证信息.
  2. 不要在'userData'中放入太多数据,因为它可能会使cookie变得太大而无法传输(某些浏览器会限制cookie大小).

而已.从上面的指导中,没有人被明确告知"将userData仅限于身份验证信息是最佳做法." 我当然没有看到一个文档说"将授权或角色信息放入'userData'是个坏主意,因为..."

推出最佳实践?

关于两个设计选择相同的我自己的答案是"不".我想提出我的论点,并在以下情况下向你学习:

  1. 你同意.
  2. 你不同意,因为我做了不必要的大惊小怪.
  3. 你不同意; 虽然我的观点是有效的,但有理由说明为什么我的思想最终是不对的.

希望最佳实践概念能够作为答案出现.现在我的论点......

我的论点

我认为应该采用第二个设计故事,因为它代表了更好的模块化:角色信息完全在"MyRoleProvider"中处理.第一个选项不必要地混合认证(从cookie中提取标识)和授权问题.实际上,所有内置的ASP.NET安全机制都将这两个主题分开; 基本ASP.NET功能永远不会在authcookie中存储role-info.如果有人想要确认这一点,请尝试反映这些类:FormsAuthenticationModule,FormsAuthentication,带有RolePrincipal实现的IPrincipal,以及带有FormsIdentity实现的IIdentity.

ASP.NET RolePrincipal值得一个特别的亮点.它允许role-info确实存储在cookie中,但它是与auth-cookie分开的第二个cookie.此外,这种特殊的习语仍然涉及与RoleProvider的协商.请参阅此MSDN文档示例部分.

进一步调查RolePrincipal,让我们看一下RolePrincipal.IsInRole().虽然任何此类IPrincipal派生类以编程方式组合了身份和角色信息,但内部实现仍将RoleProvider维护为角色信息的唯一来源(请注意引用Roles.RoleProviders...):

    public bool IsInRole(string role)
    {
        if (this._Identity != null)
        {
            if (!this._Identity.IsAuthenticated || role == null)
            {
                return false;
            }
            else
            {
                role = role.Trim();
                if (!this.IsRoleListCached)
                {
                    this._Roles.Clear();
                    string[] rolesForUser = Roles.Providers[this._ProviderName].GetRolesForUser(this.Identity.Name);
                    string[] strArrays = rolesForUser;
                    for (int i = 0; i < (int)strArrays.Length; i++)
                    {
                        string str = strArrays[i];
                        if (this._Roles[str] == null)
                        {
                            this._Roles.Add(str, string.Empty);
                        }
                    }
                    this._IsRoleListCached = true;
                    this._CachedListChanged = true;
                }
                return this._Roles[role] != null;
            }
        }
        else
        {
            throw new ProviderException(SR.GetString("Role_Principal_not_fully_constructed"));
        }
    }
Run Code Online (Sandbox Code Playgroud)

这种ASP.NET"一站式"深度假设角色信息的位置,这就是为什么角色信息应该整合到RoleProvider中.总之,我声称:

  1. 如果你一个cookie存储角色信息,为什么ASP.NET没有一个内置功能的原因,结合到身份验证cookie的,也正是因为ASP.NET维持一个强烈的不同供应商之间的关系分离.
  2. 任何RoleProvider都应该知道可能在哪里找到role-info,无论是在cookie,会话还是其他方面.

结论:

不要将role-info放入auth-cookie中,并确保您的(自定义)RoleProvider 知道找到角色信息的所有位置,无论是数据库,Web服务,会话,缓存还是cookie.

同意?不同意?思考?

Not*_*tMe 7

有许多不同的关注点和设计选择可用于决定实际缓存信息的位置,无论是cookie,会话还是其他提供商.

当然,第一个问题是你是否应该缓存它.当然,人们担心不断访问数据库以获得相当静态的信息.然而,同样关注的是能够立即锁定某人.

只有在不需要立即响应时才能实现缓存.因此,在缓存授权方面没有最佳实践..如果您的应用程序不需要这种安全级别,当然也没有关于缓存它的最佳实践.

假设上述问题不是问题,那么就会有位置权衡.

Cookie
如果您将其放入Cookie中,则可以捕获并随后重播.此外,它会略微增加您的互联网流量,因为cookie会在每次请求时传输.

会话
如果将其置于会话中,则可以将自己限制为单个Web服务器,也可以将会话状态存储在整个Web场可访问的位置.如果采用后一种方式,那么你完全可能将会话存储在某个数据库的某个地方,从而完全破坏了你在会话开始时的理由.

Memcache或其他
这类似于在会话中存储角色; 但是它通常存储在单独的服务器上的内存中,并且通常很快.缺点是对于负载平衡的Web场,这可能会增加另一个故障点......除非它被正确聚类.此时您已经增加了项目开发,部署和维护成本....


最终,没有最好的做法.只有一堆依赖于情况的权衡取舍.坦率地说,对于这种类型的数据,我根本不会缓存它.它通常相对较小,对它的查询通常非常快.如果我们谈论成千上万的用户,我可能会考虑它,但在那个层面上还有许多其他操作方面的考虑因素最终会使这里的选择显而易见.


Eri*_*sch 4

在我看来,你问的是一个荒谬的问题。头脑清醒的人不会将角色数据存储在身份验证 cookie 中。ASP.NET 并没有这样做,因为它们提供了将其存储在加密的单独 cookie 中的 RolePrincipal。

无论如何,整个 cookie 问题毫无意义,因为这是 RolePrincipal 的实现细节。应用程序不应该知道角色数据的存储位置。

所以我问你的问题是...为什么我们要进行这样的讨论?你问,最好的做法是做一些与系统的做法相反的事情,然后争论为什么你不应该以这种没人会使用的方式来做。

另外,您关于RoleProvider必须处理 cookie 的评论是不正确的。RoleProvider 不会创建RolePrincipal,这是在框架内部完成的。是否使用cookie的选择不在 中RoleProvider,而是由RoleManagerModule框架类提供,并且方法IPrincipal由框架实例化。

中的例子RolePrincipal与 无关RoleProvider。事实上,RoleManagerModule控制这个功能。 RoleManagerModuleHttpModule安装到 IIS 中并作为管道的一部分运行的。它甚至不知道RoleProvider,基本上这意味着角色是从非常低的级别的 cookie 填充的,当 `RoleProvider 开始运行时,如果它发现角色已经存在,它什么也不做。