用户角色 - 为啥不存储在会话中?

Posted

技术标签:

【中文标题】用户角色 - 为啥不存储在会话中?【英文标题】:User roles - why not store in session?用户角色 - 为什么不存储在会话中? 【发布时间】:2010-12-12 22:07:24 【问题描述】:

我正在将 ASP.NET 应用程序移植到 MVC,并且需要存储与经过身份验证的用户相关的两个项目:角色列表和可见项目 ID 列表,以确定用户可以看到或看不到的内容。

我们过去曾将 WSE 与 Web 服务一起使用,这使得事情变得难以置信地复杂并且无法正确调试。现在我们放弃了我一直期待的 Web 服务,以大幅简化解决方案,只需将这些内容存储在会话中。一位同事建议使用角色和会员提供者,但在调查后我发现了一些问题:

a) 它与 WSE 存在相似但不同的问题,因为它必须以非常受限的方式使用,即使编写测试也很棘手;

b) RolesProvider 的唯一缓存选项是基于我们基于安全理由拒绝的 cookie;

c) 它带来了无穷无尽的并发症和多余的负担;

简而言之,我们想要做的就是将两个字符串变量存储在用户的会话中或以安全的方式等效的东西中,并在需要时引用它们。到目前为止,看似十分钟的工作已经进行了几天的调查,并且为了使问题更加复杂,我们现在发现会话 ID 显然可以被伪造,请参阅

http://blogs.sans.org/appsecstreetfighter/2009/06/14/session-attacks-and-aspnet-part-1/

我一直认为没有简单的方法可以完成这项非常简单的工作,但我觉得这难以置信。

任何人都可以:

a) 提供有关如何使 ASP.NET MVC 会话像我一直认为的那样安全的简单信息?

b) 建议另一种简单的方法来为登录用户的角色等存储这两个字符串变量,而不必如上所述用另一个复杂的噩梦替换?

谢谢。

【问题讨论】:

【参考方案1】:

如果会话不能被劫持,将用户的角色信息存储在服务器端会话中是安全的。更广泛地重申这一点,如果经过身份验证的会话被劫持,用户角色信息的存储位置并不重要。

我建议不要太相信您链接到的文章,但是您的链接链接到的 2002 年的老式报告很有趣。以下是我的收获:

    不接受嵌入在 URL 中的会话 ID。

    专注于消除跨站点脚本编写的危险,即扫描所有用户提供的数据并解析出可执行的 java 脚本。

    为完整的域(例如 myapp.mydomain.com)发出 cookie

    在高级 DNS 运营商处托管您的域,例如一种只允许从预设的远程 IP 地址更改 DNS。

    不要发出持久会话 cookie。

    如果有人到达登录页面,并且 sessionID 已经与经过身份验证的会话相关联,则重新发出会话 cookie。

    更好的是,始终在成功验证时发出新的会话 cookie 并放弃前一个会话。 (这可以在 IIS 中配置吗?)

【讨论】:

【参考方案2】:

实现安全连接的唯一方法是使用 SSL。任何低于此的值,您只需在“足够安全”时进行评估。

会话变量可以很好地存储值,但 Web 服务器可能不时被回收,这将导致会话丢失。发生这种情况时,您将不得不重新验证用户并再次设置会话变量。

会话变量本身是完全安全的,除非您专门将其复制到响应中,否则它永远不会离开服务器。

【讨论】:

我应该说,我们确实使用 SSL,所以那里没有问题。此外,我们从来没有遇到过会话回收问题,所以我并不担心。 至于会话变量是完全安全的:这就是我的想法,但我链接到的文章表明,可以通过各种方式诱骗用户加入现有会话,从而与随后登录并因此将他们自己的所有角色存储在那里以供其他人使用的经过身份验证的用户。显而易见的解决方案是将 IP 地址存储在会话中并每次检查它,但显然在请求中也很容易伪造它。虽然我无法做出任何建议的方式 加入现有的会话工作我更想知道他们为什么不这样做,而不是仅仅依靠我作为黑客明显缺乏的技能。如果我对此有信心,那么我认为我们已经解决了问题,但到目前为止我还没有。 我应该补充一点,我可以手动修复会话 cookie,但这依赖于知道要设置的会话 ID,而且由于我们使用 SSL,我认为这不是问题。黑客攻击将依赖于向用户发送链接,该链接让他们而不是黑客加入现有会话(由黑客实例化)然后登录。 SSL 连接有它自己的会话 id,它没有存储在 cookie 中,所以关于欺骗会话 id cookie 的文章不适用。 SSL session id 没有公开,即使你设法得到它,你也不能在另一个 SSL 连接中重复使用它。【参考方案3】:

您是否考虑过在 MVC 中设置自定义 Authorize 标签。我在另一个question 中举了一个例子。

在初始授权(登录屏幕或会话开始)时,您还可以使用 IP 地址播种会话值。然后在您的自定义授权中,您还可以验证 IP 是否仍然匹配。这将有助于确保有人没有“窃取”该人的会话。每次访问会话数据时,只需确保传递请求者的 IP 并对其进行一些检查。

【讨论】:

【参考方案4】:

您是否尝试在客户端级别控制对功能的访问?这是我公开角色和项目以控制客户端功能的唯一原因。

或者,您可以创建一个函数来获取允许用户角色使用的项目,然后即使在返回给 Web 应用程序的项目之外调用该函数,您也可以阻止用户访问它们。

4Guys 似乎展示了如何使用角色控制功能。

【讨论】:

【参考方案5】:

我过去使用的方法是在 SSL 旁边使用 cookie 的对称加密。在响应中加密用户信息,在请求中解密。我并不是说这是万无一失或 100% 安全的,我也不想在银行应用程序上这样做,但它对于许多用途来说已经足够了。

会话变量的主要问题是,如果您将它们存储在进程中而不是持久化它们,那么您需要将“粘性”会话应用于网络场环境中的负载平衡。 Guffa 是正确的,没有这种持久性会话变量偶尔会丢失,从而导致糟糕的用户体验。

粘性会话会导致负载平衡不均匀,可能会降低能够横向扩展的价值。

如果您要保留会话,以便您的网络场中的所有服务器都可以访问它们,您最好使用 Guid 来识别用户,在 cookie 中加密并从每次都存储您的数据。

【讨论】:

【参考方案6】:

我的明显问题是,为什么要在会话中存储用户角色?

这是我对您的问题的回答,这有什么帮助。我附上了一个小型演示应用程序,供您查看和理解我的观点。在 Visual Studio 中打开此项目时,单击顶部的项目选项卡并选择 asp.net 配置。从将显示的页面中,您可以进行用户管理。

您需要以某种安全方式存储用户的角色吗?这个问题的答案是,当我们拥有 asp.net 成员资格、配置文件和角色框架来帮助我们解决这个问题时,您无需担心存储任何用户的角色。您需要做的就是在 aspnet 数据库中创建一个角色并将该角色分配给用户。

接下来你想以某种安全的方式存储两个字符串。我建议您使用用户配置文件来存储用户特定信息。这样,您就可以从 profilecommon 类中获得所需的任何信息。

另请参阅我的博客末尾的附加演示应用程序http://blogs.bootcampedu.com/blog/post/Reply-to-http***comquestions1672007user-roles-why-not-store-in-session.aspx

【讨论】:

【参考方案7】:

只是一个建议,你可以考虑使用这个小库:

http://www.codeproject.com/KB/aspnet/Univar.aspx

它有一个 cookie 的服务器端实现,因此所有 cookie 都可以存储在服务器上,而 asp.net 身份验证用于识别用户。它支持加密,而且非常灵活,可以很容易地从一种存储类型切换到另一种存储类型。

【讨论】:

以上是关于用户角色 - 为啥不存储在会话中?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 PostgreSQL 将用户和组合并为角色?

为啥 SQL Server 不允许我启用混合身份验证模式,以便我可以使用 sa 用户将角色分配给其他用户?

为啥 Sitecore 创建具有所有 Extranet 角色的虚拟用户?

XenServer 如何计算会话的角色?

cochdb 权限角色始终“未授权”

Laravel:注销特定用户