基于会话和基于令牌的身份验证

45

我想知道哪种身份验证方式更安全,以及为什么?是基于会话的身份验证还是基于令牌的身份验证?

我知道会话也可以用于其他事情,但现在我只对身份验证感兴趣。

如果使用令牌,是否真的不会在服务器端存储任何信息(甚至不会在内存中)?如果是,那么它如何识别已过期的令牌,因为它们也是使用相同的密钥签名的呢?


1
https://security.stackexchange.com/questions/81756/session-authentication-vs-token-authentication - Sachin Yadav
1个回答

7
上面评论中涉及到的信息安全问题有很多相关的信息。但是,这个问题提出了一些额外的关注点,需要解决:

安全性

如果不知道服务器实现的任何内容,那么这两种方法都可能很安全。基于会话的身份验证主要依赖于会话标识符的可猜测性(正如在信息安全答案中所述,它本身就是一个非常简单的令牌)。如果会话标识符是单调递增的数字 id,那么它就不太安全,反之,它可以是具有巨大密钥空间的不透明加密强度唯一 ID,从而使其非常安全。你可能将使用你选择的服务器框架提供的会话实现,因此你需要检查它。之后,使用会话身份验证,你的服务器实现需要验证服务器存储的会话是否包含相关的授权(即用户帐户数据、角色等)-由于许多服务器会话框架默认情况下会自动生成空会话,因此不能仅依靠会话存在的事实作为有效身份验证和授权的证据。

例如,PHP 的内部会话 ID 生成使用完全随机的 288 位数字(默认设置),因此被认为是安全的。另一方面,默认情况下会自动生成会话,因此必须遵守前面的注释(或禁用自动会话创建,并确保服务器仅在需要时创建会话)。
此外,如果会话 ID 使用 HTTP URL 查询字符串传递,就像旧日的默认值一样,则会话可以很容易地被窃取,这使得整个过程不安全。

令牌的安全性主要基于安全令牌生成:如果服务器以非可猜测和可验证的方式生成令牌-如信息安全答案所示。有一个天真的实现(我见过一次),可能是对已知令牌(例如用户名)进行 MD5 哈希,即使加盐也是非常不安全的。在使用加密令牌时,安全性与所使用的算法、密钥长度以及最重要的服务器密钥安全性密切相关:如果服务器密钥硬编码到服务器实现中,然后该代码开源...

存储

服务器是否需要存储任何内容通常取决于令牌的实现方式。

许多实现将“API 密钥”概念用作“令牌身份验证”,因此令牌通常只是指向记录已生成哪些“API 密钥”的数据库的一些加密安全的 ID。这需要存储,但具有更简单的实现优势,更重要的是,具有吊销令牌的能力。

另一种方法是让令牌携带自己的真实性-这使服务器基本上将令牌存储转移到客户端,并将客户端用作数据库-非常类似于 HTTP Cookie 允许服务器将一些存储要求转移到客户端(通常用于客户端特定的设置,如用户想要浅色界面还是深色界面)。

这两个模式在信息安全答案中都有很好的演示:签名和加密。

  • 签名:令牌是认证器凭据(例如用户名)和可能的令牌过期时间(如果您想要令牌过期-通常是个好主意,如果您无法撤销令牌)的一些简单编码(如JSON或CSV),然后服务器使用服务器密钥签署生成的文本并将其添加到令牌中。当客户端提交令牌时,服务器可以从令牌中提取明文,重新签署它并将新的签名与提交的令牌中的签名部分进行比较-如果它们相同,则令牌有效。在验证之后,您可能想要检查已验证的过期日期与当前时间的差异。这里的主要缺点是应注意清晰的身份验证详细信息对于攻击者来说是强烈不足的,以便他们重新进行身份验证-否则,它会损害安全要求。即不要将密码作为令牌的一部分发送,也不要发送任何其他内部详细信息。

  • 加密:再次编码所有相关的身份验证详细信息生成令牌,然后使用服务器密钥加密明文,并仅提交加密结果生成令牌。如果可以信任加密方案,则身份验证详细信息可以包括内部数据-但应注意,将大量加密文本脱机提供给攻击者比小签名具有更大的攻击面,而弱加密算法在此用途中的弹性将比仅签名要小。

在这两种方法中,安全性与加密/签名算法的强度密切相关-弱算法将允许攻击者反向工程服务器密钥并生成新的有效令牌而不进行身份验证。

个人笔记

我认为,基于密码令牌的身份验证往往比基于会话的身份验证更不安全,因为它依赖于(通常是单一的)开发人员从设计到实现再到部署的全部正确操作,而基于会话的身份验证可以利用现有的实现来完成大部分繁重工作,在那里很容易找到高质量、安全且经过大规模使用和测试的会话存储实现。除非有非常充分的理由说明不需要会话存储,否则建议使用密码令牌。

始终记住密码安全的第一条规则:永远不要设计自己的单次使用密码措施。


非常抱歉我发了一篇旧帖,但是基于会话的身份验证不是对数据库事务要求很高吗?这样会不会增加成本呢? - Arpit Anand
1
@ArpitAnand 通常情况下,您的应用程序已经需要使用服务器存储来存储某些数据,因此存储认证数据的成本将是微不足道的。否则,如果您想推迟投资存储,强大的自我证明加密令牌可能是一个不错的选择 - 但请注意,这需要更多的思考和实践才能做到正确 - 而且这些也不便宜。 - Guss
好的,但如果我们选择使用像 jsonwebtoken 这样的库呢?它们提供了对 node 加密库相当不错的抽象 - 更少的代码,因此出错的可能性更小! - Arpit Anand
@ArpitAnand JWT是一个具有许多选项的重要标准,您在使用实现它的库之前应该清楚地了解其目的、用途和机制。例如,使用JWT进行授权的一种失败方式是,jsonwebtoken仅支持签名而不支持加密,因此任何获得您令牌的人都可以理解您令牌的内部结构,并更好地了解如何攻击您(或者您可能会泄漏用户不应该拥有的内部数据)。 - Guss
1
不是,那是签名——这意味着接收者可以看到明文并验证您创建了它。稍微相关(刚刚看到):https://mobile.twitter.com/FiloSottile/status/1399700873798893571/photo/1 - Guss
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接