设定两个ASP.NET MVC授权/角色设计故事。两者都旨在最大限度地减少针对中间层或数据存储的命中:
或者...
同样,上述两个故事都旨在通过“缓存”角色信息来最小化击中外部商店的延迟。两者都很好。问题是,两个设计故事选择同样有效吗?如果没有,为什么?
似乎没有任何地方声明“最佳做法”,其中说“你的(自定义)RoleProvider应该始终知道找到角色信息的位置,无论是在会话,缓存,数据库等等。”
此外,似乎没有任何(可靠的)指导可以解释您不应该在authCookie中的“userData”中存储哪些类型的内容。那里的文档和指导只有两点:
就是这样。从上面的指导中,没有人被明确告知“将userData仅限于身份验证信息是最佳做法。”我当然没有看到一个文档说“将授权或角色信息放入'userData'是个坏主意,因为......”
关于两个设计选择相同的我自己的答案是“不”。我想提出我的论点,并在以下情况下向你学习:
希望最佳实践概念能够作为答案出现。现在我的论点......
我认为应该采用第二个设计故事,因为它代表了更好的模块化:角色信息完全在“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中的原因。总之,我声称:
不要将role-info放入auth-cookie中,并确保您的(自定义)RoleProvider 知道找到角色信息的所有位置,无论是数据库,Web服务,会话,缓存或者是一个cookie。
同意?不同意?想法?
答案 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
控制着这个功能。 RoleManagerModule
是HttpModule
,它安装在IIS中并作为管道的一部分运行。它甚至不知道RoleProvider
,基本上这意味着角色从cookie中以非常低的级别填充,当`RoleProvider开始运行时,如果它已经找到了角色,它什么也没做。