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

时间:2012-10-18 19:08:42

标签: 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大小)。
  3. 就是这样。从上面的指导中,没有人被明确告知“将userData仅限于身份验证信息是最佳做法。”我当然没有看到一个文档说“将授权或角色信息放入'userData'是个坏主意,因为......”

    推出最佳实践?

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

    1. 你同意。
    2. 你不同意,因为我做了不必要的大惊小怪。
    3. 你不同意;虽然我的论证是有效的,但甚至还有更好的论据,说明为什么我的思想最终是不对的。
    4. 希望最佳实践概念能够作为答案出现。现在我的论点......

      My Argument(s)

      我认为应该采用第二个设计故事,因为它代表了更好的模块化:角色信息完全在“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的协商。请参阅example section of this MSDN documentation

      进一步调查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"));
              }
          }
      

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

      1. 如果 在cookie中存储角色信息,那么ASP.NET没有内置功能将其组合到auth-cookie中的原因正是因为ASP.NET维护强烈地将不​​同提供者之间的关注点分开。
      2. 任何RoleProvider都应该知道可能在哪里找到角色信息,无论是在cookie,会话还是其他方面。
      3. 结论:

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

        同意?不同意?想法?

2 个答案:

答案 0 :(得分:7)

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

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

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

假设上述问题不是问题,那么就需要与地点进行权衡。

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

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

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


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

答案 1 :(得分:3)

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

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

所以我的问题是......为什么我们甚至讨论这个问题?你问的最好的做法是做一些与系统如何做的相反的事情,然后争论为什么你不应该这样做,没有人会用。

此外,您对RoleProvider必须处理cookie的评论不正确。 RoleProvider不会创建RolePrincipal,这是在框架内完成的。是否使用cookie的选择不在RoleProvider中,而是由RoleManagerModule框架类提供,以及框架实例化IPrincipal的方式。

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