避免在无状态 Web 应用程序架构中的每个请求上访问 DB 来验证用户身份?

信息安全 Web应用程序 验证 数据库 饼干 会话管理
2021-08-09 19:53:13

概括

一旦用户登录到网站并验证了他的用户名/密码凭据并建立了活动会话,是否可以避免针对该用户的每个请求访问数据库?在会话生命周期内安全地验证后续请求,同时最小化数据库查询和其他内部网络流量的推荐方法是什么?

背景

在无状态 Web 应用服务器架构中,每个请求都不知道用户的任何先前活动,因此有必要针对来自该用户的每个请求查询数据库(通常通过查询存储在 cookie 中的会话 ID 和在请求标头中传输)。但是,如果一些基本信息被加密并存储在该会话 cookie 中,该 cookie 有足够的信息来验证用户的非敏感、不可编辑的请求怎么办?对于此类请求,您可以作为一个示例,在会话数据中加密并存储用户 ID 和尽可能唯一标识他的机器的内容(用户代理 + ip 地址)。用于加密数据的密钥可能每天都在变化,这使得任何黑客都难以在不同的机器上克隆会话数据。当 Session 过期时,您需要完全验证用户的凭据。事实是,入侵用户会话的最大威胁是有人使用他或她无人看管的用户计算机。我是否应该不担心这一点,让 Web 应用程序服务器和数据库之间的某种程度的缓存负责加快身份验证过程?虽然这似乎是不必要的优化,但它似乎是提高效率的成熟候选,因为每个请求都需要这个过程。感谢您的任何建议!我是否应该不担心这一点,让 Web 应用程序服务器和数据库之间的某种程度的缓存负责加快身份验证过程?虽然这似乎是不必要的优化,但它似乎是提高效率的成熟候选,因为每个请求都需要这个过程。感谢您的任何建议!我是否应该不担心这一点,让 Web 应用程序服务器和数据库之间的某种程度的缓存负责加快身份验证过程?虽然这似乎是不必要的优化,但它似乎是提高效率的成熟候选,因为每个请求都需要这个过程。感谢您的任何建议!

4个回答

的,这是可能的,而且这种技术被广泛使用。

与有状态会话相比,它确实有一些小缺点:

  1. 它不支持强注销。如果用户单击注销,则会从浏览器中清除 cookie。但是,如果攻击者捕获了 cookie,他们可以继续使用它,直到 cookie 过期。
  2. 使用服务器端秘密创建令牌会产生单点故障:如果秘密被捕获,攻击者可以冒充任何用户。

决定使用无状态会话还是有状态会话取决于您的性能和安全要求。网上银行倾向于使用有状态会话,而繁忙的博客倾向于使用无状态会话。

您提出的方案需要进行一些调整:

  1. 加密令牌并不能防止其被篡改。您想使用可以保护篡改的消息验证码 (MAC)。您可能还想使用加密,但这并不重要。
  2. 您需要在令牌中包含时间戳并对其有效性设置时间限制。大约 15 分钟是明智的。通常你会在超时前不久自动重新发布,并且通常重新发布会导致数据库命中(尽管即使这样也可以避免)
  3. 不要在令牌中包含用户的 IP 地址。由于调制解调器重置、更改 WiFi 热点、负载平衡代理等原因,大约 3% 的用户将在 Web 会话期间合法更改 IP 地址。虽然您可以在令牌中包含用户代理,但这样做是不正常的 - 如果您确定自己知道自己在做什么,可以将其视为一种高级技术。
  4. 如果攻击者捕获了会话 cookie,他们就可以冒充该用户。你真的无能为力。相反,首先要全力防止攻击者捕获 cookie。使用 SSL,使用“安全”cookie 标志,修复所有跨站点脚本缺陷等。并且有一些用户建议在他们的计算机无人看管时锁定他们的屏幕。

我希望这对你有帮助。如果有任何不清楚或您需要更多信息,请发表评论,我会看看是否可以进一步帮助您。

通常,可以在客户端“存储”状态信息,甚至是身份验证数据等敏感信息;这种存储用于节省服务器上的资源,例如最小化数据库负载。请参阅这些先前的问题:

简而言之,每当您想在服务器上存储一些信息以便在同一个客户端返回时进行查找时,您可以将其作为 cookie 发送给客户端。您可能需要加密,因为该信息可能是“私人的”,从某种意义上说,您不想将其显示给客户本人。您可能需要完整性,因为您不希望客户端能够在未经您同意的情况下更改数据。因此,您既想要加密又想要MAC,或者更好的是,这些漂亮的加密模式中的一种都可以正确完成(GCM是经常引用的标准)。

通常,当您在客户端和客户端上存储状态信息时,您将失去对该信息生命周期的一些控制。客户端可以选择不发回 cookie,即模拟一个新的、新鲜的客户端;此外,客户端可能会发回旧的 cookie 值。这对您来说是否是个问题取决于您的具体情况。您可能希望在 cookie 数据中包含一个时间戳,以便您识别确实太旧的 cookie 值。

有一些方法可以解决这个问题(我已经看到在 REST API 中使用了这种方法)。

  1. 使用 HTTPs 进行身份验证,然后使用无状态 API。
  2. 使用基本的 HTTP 身份验证方法并在每个请求中使用过期的 tokenID。

无论如何,如果您需要身份验证和无状态身份验证,则需要在应用会话中管理身份验证。验证凭据后,您实际上可以进行数据库查询,而无需通过受信任的用户或类似用户再次进行创作。

确保不允许任何其他用户直接连接到数据库,而不是您在凭据检查后允许这样做的用户。

我相信您明白,省略基于先前身份验证的身份验证会使您的 Web 应用程序成为会话应用程序。不是会话状态已通过身份验证吗?知道你正在学习有一个会话; 您可能会问自己为什么需要会话 lees 应用程序。通常人们想要会话 lees 应用程序有两个主要原因: 可以将请求传递到不同的服务器,而不必担心客户端和服务器场的任何成员之间的任何依赖关系。大量用户同时访问时的内存联动。即使在会话应用程序上,您也可以通过使服务器在身份验证时发出加密的签名令牌来满足这些要求,以便网络场的其他成员可以验证该令牌以了解用户可能是合法的。仍然可以进行模拟,因为以下请求需要相同的令牌。您可以在请求 http 标头和 IP 中包含令牌数据以限制其使用,但中间代理仍然可以通过执行 NAT 和复制客户端标头来使用令牌。然后,使中间人攻击无懈可击的唯一方法是通过 https 保护身份验证请求,并让客户端向您发送带有凭据的随机生成的密钥,该密钥将用于解密请求的签名,每个请求中的客户端将加密请求的一些数据作为签名。加密的数据可以是会话 ID 和来自预建立定序器生成器的序列元素。不要使用简单的加一,因为它的行为是可预测的。在每个请求中,此签名与以前的签名不同,您可以确定客户端已通过身份验证。如果定序器生成器总是递增,您可以缓存用于在完整检查之前进行简单检查的最后一个元素;广播场的其他成员会话 ID 中使用的序列元素,他们只会在元素无效时回答。如果一个元素序列已在应答服务器中的先前请求中使用过,或者如果该序列的下一个元素在缓存中超时,则该元素序列无效。防止内存沿袭是一种简单的方法,即为每个成员场实施 SQL 服务器,以使此信息持久保存,并且仅在内存中保留最常用的信息。由于通信不安全,用于农场成员之间通信的网络设备必须全部由应用程序所有者管理。