【问题标题】:Is forms Authentication Ticket always Encrypted?表单身份验证票是否始终加密?
【发布时间】:2017-07-15 22:25:34
【问题描述】:

我的想法:由 FormsAuthentication.SetAuthCookie 创建的 cookie 始终是加密的。

这是我在查看 Microsoft 网站时的理解,其中说票证是使用 Machine.config 中的 machineKey 加密的: https://support.microsoft.com/en-ca/help/910443/understanding-the-forms-authentication-ticket-and-cookie

为了 100% 确定它是加密的,我运行了以下代码:

在一页上:

FormsAuthentication.RedirectFromLoginPage(user.user_name, false);

在下一页:

HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];

FormsAuthenticationTicket authTicket = 
FormsAuthentication.Decrypt(authCookie.Value);

我看到 cookie 的值是加密的,而且解密得很好。

但是,在这里查看最佳答案时:FormsAuthentication: Is it secure? 似乎不建议在 cookie 中存储敏感信息。在上面的链接中,他甚至说“我认为你是以纯文本形式存储 cookie”。

在此处查看第二级答案时也是如此:Storing more information using FormsAuthentication.SetAuthCookie

如果 cookie 是使用 machineKey 自动加密的,为什么假定他们以纯文本形式存储它,? 为什么在此处存储敏感信息会出现问题?

附:我需要存储有关已登录用户的敏感信息。

【问题讨论】:

  • 只是因为它被加密并不意味着有人无法用足够的时间和精力来解密它。解密临时身份验证令牌并没有那么糟糕,因为当您发现它时,它已经过期了。另一方面,解密用户密码...
  • 谢谢。抱歉,我对此有点陌生,但这是否意味着通过 HTTPS 发送用户密码也不那么安全?

标签: c# asp.net asp.net-mvc forms-authentication


【解决方案1】:

不是一直加密吗?

如果您使用 vanilla forms 身份验证,则默认情况下会加密 cookie。然而,它是一个框架——你可以自定义它——事实上,如果你熟悉 API,你可以设置任何你想要的 cookie。但是你必须不遗余力地做到这一点。

那另一张海报呢?

至于 SO 问题"Forms authentication...Is it secure?"。我不同意这个答案。正确答案是:您应该永远将密码存储在 cookie 或其他任何地方,加密或纯文本。密码应该是散列的,而不是存储的。

我可以将密码存储在 cookie 中吗?

表单身份验证应该工作的方式,您不需要将密码存储在其中。 cookie 是防篡改的,如果只有您的网站可以创建 cookie,并且您的网站仅在用户提供有效凭据时才创建 cookie,那么仅 cookie 的存在就足以推断出正确的密码在早些时候的某个时间提出。但是,cookie 应包含用户 ID 或获取用户 ID 的某种方式。

为什么我不应该将我所有的用户数据都放在 cookie 中?

没有在 cookie 中存储太多的主要原因是它会消耗每个请求的带宽,包括对图像、样式表和脚本的请求。将 cookie 作为标头添加到浏览器传递的每个 GET 和 POST 中。此外,cookie 的解密每次都会占用 CPU,即使您在较早阶段终止 SSL,也不会卸载此处理。因此,如果您想在其中存储几个标志或字符串,很好,但不要存储任何大型数据结构。如果您需要存储在会话中持续存在的大量数据,请考虑改用session variables。或者,如果您正在争取一个无状态的网络应用程序,也许将会话数据存储在数据库中,并将数据库标识符存储在 cookie 中。

如果 cookie 是加密的,为什么我需要小心将敏感数据放入其中?

因为时不时会出现vulnerabilites like this one。如果客户端机器上不需要数据,则也不需要加密形式的数据。最好把这些东西放在绝对需要的地方。

如果您选择使用会话状态

如果机密很敏感,那么您应该只使用进程内会话状态。如果您使用 SQL Server 会话状态,your data can be easily decrypted。另一种方法是在会话状态下加密凭证,并且仅在您使用它们时解密它们,这将是一件苦差事,而且很容易被忽视。您还可以编写一个自定义会话状态提供程序,将加密覆盖在所有内容上,但随后您会看到性能损失,因为几乎每个页面请求都完成了会话状态检索。所以我会去进程内。

另外,请务必关注Microsoft's guidance 保护会话状态。

如果你想变得现代一点

如果您正在关注微服务和 REST 时尚,您可以执行以下操作:

  1. 构建一个 RESTful 微服务,其唯一目的是安全地存储这些凭据。该服务应仅在您的 Web 服务器的本地子网而非 Internet 上可用,并且应使用客户端证书和 IP 白名单进行保护。

  2. 在您的 REST 客户端和 REST 服务器上实现缓存控制,并将缓存过期时间设置得相当高,可能是 24 小时。

  3. 当网站需要凭证时,调用微服务。如果您尊重缓存标头,那么您的 REST 客户端也应该缓存该值,这将避免重复调用服务。

但如果你真的想使用 cookie

如果您需要存储的凭据是用户自己的凭据,例如您正在充当他们使用的某些 Google 应用程序的 API 的传递者,那么我认为您可以将这些内容放入 cookie 中。毕竟,用户可能在自己机器上的某个地方拥有它。 AES-128 pretty much can't be brute forced,如果您愿意,您可以使用 AES-256 来证明您是认真的。

如果证书是地球上任何普通公民都不应该拥有的东西,例如银行主机的应用程序密码,我不会这样做。

【讨论】:

  • 很好的答案。它引导我提出 2 个后续问题: 1. 如果理想情况下我们不应该将任何敏感信息放在那里,为什么默认情况下首先加密 cookie? 2. 好像到了一定的大小,存储在cookie中会更好。在那个大小之后,最好存储在其他地方,比如 session。当然,这可能是一个见仁见智的问题,但您会说这个阈值在 kb 中大致在哪里?
  • 所以如果我真的需要存储一些敏感信息,你会推荐 session over 加密的 cookie(假设 HTTPS)?不像密码那么敏感,但仍然敏感:外部 API 的一些访问令牌。我意识到通常不存储敏感信息很容易逃脱,但对于我的具体情况,我别无选择。
  • 谢谢吴约翰
猜你喜欢
  • 1970-01-01
  • 2017-10-26
  • 2012-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多