用于 Web 和移动应用程序的 API 的 JWT 或会话 cookie?

信息安全 Web应用程序 移动的 饼干 会话管理 jwt
2021-08-24 14:05:15

在过去的几天里,我一直在阅读关于这个主题的所有内容,但我无法决定什么是最好的方法。

仅有的两个要求是:

  • 我需要知道已登录的用户以及他们拥有的每个会话,以便用户能够看到包含此​​信息的列表并能够关闭他们选择的任何会话。

  • 两个应用程序都应该使用相同的 rest API 端点。

起初我使用会话 cookie,并使用 setCredentials=true 调用 API,但我发现移动应用程序处理 cookie 的方式不同,我无法控制(例如,它们在过期之前由于各种原因被删除)。我曾考虑将 cookie 保存在本机存储中并将其附加到每个请求中,但我无法以任何方式访问 cookie,因为 httpOnly 设置为 true。解决方案是将 httpOnly 设置为 false,但这样我会暴露 cookie,我不确定应该采取哪些安全措施来保护 cookie 不被盗或篡改。

另一种解决方案是使用 JWT 并将其存储在 web/native 存储中。我还将每个仍然有效的令牌(使用密码算法散列)存储在一个表中,以获取登录用户及其会话的列表,以及另一个用于当用户选择结束特定会话/更改密码/时的无效令牌表等等。但我再次不确定我应该采用这种方法的安全措施。我也应该加密令牌吗?我正在考虑向其附加有关请求令牌的设备的数据,以始终检查请求令牌的设备是否是使用它的设备。我还应该做些什么来保护这个令牌?

如果我正确实施其中任何一个选项,哪个对网络和移动设备都更安全?

2个回答

在详细介绍之前,我会说会话 cookie 和 JWT 都适用于您的情况,如果正确实施,两者都是安全的。我个人会选择 JWT,因为它更容易获得最新信息或现成的解决方案。

智威汤逊

JWT 确实是为无状态授权而设计的,但您仍然可以将它们用于会话。您需要特别注意使用访问/刷新令牌模型,您可以在其中跟踪数据库中的活动刷新令牌。

在加密方面,JWT 标准主要有两种实现方式,即 JWS(签名令牌)和 JWE(签名然后加密令牌)。您要记住的是,签名令牌的签名已经确保了令牌的完整性。如果您还在令牌中传递您希望从客户端隐藏的敏感信息,您将只实施 JWE 。然而,JWT 本身并不能解决中间人攻击的问题,因此您应该记住在传输令牌时使用 SSL。

您的 Web 应用程序和移动原生应用程序之间的令牌存储会有所不同。对于移动应用程序,您应该将它们存储在为此目的而设计的操作系统的 Keychain/Keystore(很可能通过包装器)中。另一方面,在浏览器上存储 JWT 的位置仍然是一个颇具争议的话题,因为存储在 webstorage(sessionStorage/localStorage)中容易受到 XSS 攻击,而存储在 cookie 中容易受到 CSRF 的攻击。

据我所知,总体趋势是避免使用网络存储,因为它的攻击面较大,但老实说,我已经看到了这两种方法的示例。对于单页应用程序,您还可以考虑将令牌保存在内存中而不进行持久存储。

会话 Cookie

在不知道您的移动应用程序的详细信息的情况下,很难说,但根据我的经验,如果您使用的是 Google/iOS 提供的 CookieManager/NSHTTPCookieStorage 机制,则应该不会出现您描述的删除 cookie 的问题。

在浏览器上存储 cookie 需要您保护它免受 CSRF 的影响。您应该使用什么保护将在很大程度上取决于您的特定服务器实现和限制,我认为您应该查看OWASP上的资源或提出更具体的问题。

你信任你所有的客户端代码吗?如果是,您可以将会话 ID 存储在本地存储中,并确保在每个 HTTP 请求中提交它们。在您的后端,只需有一个表,其中会话 ID 哈希作为主键,用户 ID 作为外键,以及到期时间。不要保留已删除会话的列表,只需删除该行(或将其标记为已删除)。

cookie 的风险在于,它们会随每个 HTTP 请求一起发送到您的域,即使它来自假客户端。这称为CSRF除非您有某种 CSRF 保护,否则请避免使用 cookie 并使用本地存储。

当然,如果您不能信任所有客户端代码,那么您将需要另一种解决方案。

此外,如果您使用 HTTPS,那么会话 ID(cookie 或表单提交)将被加密。