表单身份验证票证是否始终加密?

Is forms Authentication Ticket always Encrypted?

我的想法:FormsAuthentication.SetAuthCookie 创建的 cookie 总是加密的。

这是我在看微软网站时的理解,上面说门票是使用 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 中存储敏感信息。上面的link,他竟然说"I presume you were storing the cookie in plain-text".

在这里查看二等答案时也是同样的事情:Storing more information using FormsAuthentication.SetAuthCookie

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

P.S。我需要存储有关登录用户的敏感信息。

不是一直加密吗?

如果您使用 vanilla 表单身份验证,cookie 默认是加密的。然而,它是一个框架——您可以自定义它——事实上,如果您了解 API 的方式,您可以设置任何您想要的 cookie。但是你必须竭尽全力才能做到这一点。

那张海报呢?

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

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

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

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

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

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

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

如果选择使用session状态

如果机密是敏感的,那么您应该只使用 in-proc session 状态。如果使用 SQL 服务器 session 状态,your data can be easily decrypted。另一种方法是加密处于 session 状态的凭据,并且仅在您使用它们时对其进行解密,这将是一件繁琐且容易被忽视的事情。您还可以编写一个自定义 session 状态提供程序来覆盖所有内容的加密,但是您会看到性能损失,因为几乎每个页面请求都会完成 session 状态检索。所以我会去 in-proc.

此外,请务必遵循 Microsoft's guidance 确保 session 状态。

如果你想要现代一点

如果您追随微服务和 REST 潮流,您可以这样做:

  1. 构建一个 RESTful 微服务,其唯一目的是安全地存储这些凭据。该服务应该只能在您的网络服务器的本地子网上使用,而不是互联网,并且应该使用客户端证书和 IP 白名单来保护。

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

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

但是如果你真的想使用 cookie

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

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