服务器不是将随机生成的 session 字符串作为服务访问 key (也称为“身份验证 token ”)发送给客户端,而是将它们插入数据库以维护一组用户 key 关系,以便随后对每个服务请求进行验证。服务器不会执行以下操作,而是在分布式系统中实现类似或更好的安全性:
- 获取用户的主键(也称为“用户标识符”)
- 获取选定的 key 过期时间戳、客户端的 IP 地址(可选)以及任何其他可能值得嵌入到 key 中的内容
- 以 secret 字符串作为 key 验证签名
- 将以上所有内容序列化
- 使用只有服务器知道的 key 对结果进行对称加密,或使用服务器选择的私钥进行非对称加密
作为上述步骤结果的 session key 随后与客户端共享,例如和一 block cookies 。对于像 HTTP 这样的无状态协议(protocol),每个请求都必须使用 session key 证明客户端身份验证,上述过程由服务器反向执行,目的是恢复经过身份验证的用户标识符。
在其他条件相同的情况下,对手需要成功攻击底层密码学才能伪造 session key ,从而危及该系统的安全性。对于“其他一切”,我指的是诸如对手以某种方式从客户端获取用户 session key 并意图自己使用它之类的弱点。
我认为该方法的优点是:
- 无需在任何地方维护有效的用户 key 关系集
- 每个 key 中嵌入的过期值可确保任何人在超过特定时间点后都无法使用 key 。
- 服务器基于解密的验证可能比数据库访问成本更低。
缺点可能是:
- 服务器使 key 无效可能会被认为是有问题的:
- 即使 key 安全地嵌入,例如IP 地址,服务器可以通过将嵌入的地址与服务请求后面的地址进行比较来使用后者来验证 key ,则 IP 地址可能是伪造的
- 如果通过服务器维护一组已撤销 key 来解决 key 撤销问题,人们可能会问这比一开始维护一组用户- key 关系更好吗?
我认为这个问题已经结束,因为它可能永远不会有一个可接受的答案,因此不符合 SO 准则,但由于它仍然开放并且已经得到了有用的答案,所以我至少不会删除它。
最佳答案
系统的弱点是“登录” token 以 cookie 中的明文形式发送,无论 token 是否在数据库中,这都是同样的弱点,并且可以通过使用 HTTPS 连接来防范。
话虽如此,大多数网站不使用 HTTPS。他们做出了权衡。如果您不使用 HTTPS,并且想要比较发送经过身份验证的 cookie 与发送 cookie 是数据库 key ,那么前者与后者相比没有什么区别。
最好还包括请求的 IP 地址以及到期日期。
没有必要将 token 加密存储在 cookie 中,但是 - 它同样安全,而且更安全 straightforward发送纯文本凭证,然后发送凭证和 secret 的加密安全散列。请参阅 HMAC 了解详情。 HMAC 基本上是:
假设变量 username、expires、ip_address 和 salt (随机数)已存储在HttpOnly中曲奇饼;你提取它们,以及 cookie 中的哈希值。在您的脚本中,您有一个额外的“密码”,它永远不会直接存储在 cookie 中:
hash = hash_hmac("sha256",username+expires+ip_address+salt,"password")
此哈希的安全性基于 quality of the password 。这应该是由数字、字母和标点符号组成的随机字符串,长度至少为 20 个字符,存储在您的服务器端脚本中。
如果 Cookie 中的散列正确,您可以确定散列的字段没有被篡改!攻击者产生有意义的碰撞的机会将是亿万分之一[1]——当然超出了宇宙中所有计算机和亿万年的计算能力。如果您的密码是随机的,那么它就是安全的。
但是整个系统对于坚定的攻击者来说只是一个减速带,并且只适用于普通网站,而不适合包括支付或用户对安全的期望。如果没有 HTTPS,系统就不安全,而如果使用 HTTPS,则无需对 cookie 进行身份验证。
坚定的攻击者可以访问您的网站来恢复密码 - 在相同情况下没有什么可以阻止他们将登录详细信息恢复到数据库,因此与问题中概述的数据库方法在这方面没有什么不同。
坚定的攻击者可以复制凭据,并代表用户发送恶意请求,例如csrf等等。
等等。
[1]我低估了可能性。
关于database - 不由发布服务器存储的用户 session key 是否可以被认为是安全的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2213071/