安全和无状态 JWT 实现

Luk*_*uke 5 security authentication json http jwt

背景

我正在尝试使用 JSON Web 令牌通过我的 Web 应用程序实现令牌身份验证。

无论我最终使用什么策略,我都试图维护两件事:无状态和安全。然而,通过阅读本网站上的答案和互联网上的博客文章,似乎有些人确信这两个属性是相互排斥的。

在试图维持无国籍状态时,有一些实际的细微差别会起作用。我可以想到以下列表:

  • 在到期日期之前按用户使受损令牌无效。
  • 允许用户一次注销所有机器上的所有“会话”并使其立即生效。
  • 允许用户注销当前机器上的当前“会话”并使其立即生效。
  • 对用户记录进行权限/角色更改会立即生效。

当前策略

如果您在 JWT 中使用“发布时间”声明并结合数据库表中表示用户记录的“上次修改”列,那么我相信上述所有要点都可以得到妥善处理。

当 Web 令牌用于身份验证时,您可以查询数据库以获取用户记录并:

if (token.issued_at < user.last_modified) then token_valid = false;
Run Code Online (Sandbox Code Playgroud)

如果您发现有人盗用了用户的帐户,则该用户可以更改其密码,并且last_modified可以更新该列,从而使之前发布的任何令牌失效。这也解决了权限/角色更改不会立即生效的问题。

此外,如果用户请求立即退出所有设备,您猜对了:更新last_modified列。

这留下的最后一个问题是每个设备的注销。但是,我相信这甚至不需要访问服务器,更不用说访问数据库了。退出操作不能只是触发一些客户端事件侦听器来删除保存 JWT 的安全 cookie 吗?


问题

首先,您是否在上述方法中看到了任何安全漏洞?我遗漏的可用性问题怎么样?

一旦这个问题得到解决,我真的不喜欢每次有人向安全端点发出 API 请求时都必须查询数据库,但这是我能想到的唯一策略。有没有人有更好的想法?

ped*_*ofb 3

您对一些常见需求如何打破 JWT 的状态性做了很好的分析。我只能对你们目前的策略提出一些改进

目前的策略

我看到的缺点是总是需要查询数据库。对用户数据的微小修改可能会改变last_modified令牌并使令牌失效。

另一种方法是维护令牌黑名单。通常为每个令牌分配一个 ID,但我认为您可以使用last_modified. 由于令牌撤销操作可能很少见,因此您可以仅使用userId, 和保留一个简单的黑名单(甚至缓存在内存中) last_modified

您只需在更新用户的关键数据(密码、权限等)和currentTime - maxExpiryTime < last_login_date. currentTime - maxExpiryTime > last_modified当(不再发送未过期的令牌)时可以丢弃该条目。

无法注销该操作,仅触发某些客户端事件侦听器来删除安全保存 JWT 的 cookie?

如果您在同一个浏览器中打开了多个选项卡,则可以使用 localStorage 事件在选项卡之间同步信息以构建注销机制(或登录/用户更改)。如果您指的是不同的浏览器或设备,那么您需要以某种方式从服务器向客户端发送事件。但这意味着维护一个活动通道,例如 WebSocket,或向本机移动应用程序发送推送消息

您在上述方法中发现任何安全缺陷吗?

如果您使用 cookie,请注意您需要设置额外的保护措施以防止CSRF攻击。另外,如果您不需要从客户端访问cookie,请将其标记为HttpOnly

我缺少的可用性问题怎么样?

当令牌即将到期时,您还需要处理轮换令牌。