在标准 JWT 的基础上,DOF ofb-auth 模块提供的 JWT 工具类提供了如下几个原始 JWT 规范并不支持的特性,使其更适用于现实项目。

服务端注销

不需要服务端存储(无状态)是 JWT 相较于传统 Session 会话维持方式的优点之一。但是,服务端不存储同时也意味着无法进行服务端注销,JWT 一旦签发,过期前一直可用,就算退出登录客户端删除了 JWT,但是之前的 JWT 事实上仍然可以通过验证。

这种情况带来的安全隐患,可以通过缩短 JWT 过期时间来减小(但是过期时间变短又会带来令牌续期的问题)。

在某些对安全要求比较高的情况下,如果你确实需要在退出登录后,之前的令牌无法再使用,你不得不选择一种服务端存储方式。

DOF JWT 提供了两个钩子,一个是在签发成功后的 onJWTIssued,可以用于将新生成的 JWT 进行服务端存储(你也可以不使用这个钩子直接存储,看你喜欢哪种写法);另一个是在校验 JWT 过期时的 onJWTExpired,可以用于将已失效的 JWT 从服务端删除。

为了性能,存储 JWT 的介质最好选择如 Redis 或 Memcached 之类内存数据库;为了高可用,令牌存储最好不要和应用层存储耦合。

密钥版本管理

一般项目中的 JWT 实现,均使用了单一的密钥来对 Header + Payload 进行签名,这种方式的不方便之处在于,如果我想更换密钥的话(比如由于安全原因可能会需要定期更新密钥),那之前使用旧密钥签发的还未过期的密钥就会立刻作废,导致已认证过的正保持登录的客户端会被无辜地强制退出系统,然后要求重新认证/登录。

这样带来的用户体验肯定是不好的,尤其是用户数很大的情况下,有些会话不能由服务端说作废就作废。比如,直播过程中的相关的接口调用使用了 JWT 认证方式,如果在直播期间作废,那么可能导致主播集中下线。

因此我们需要对 JWT 签名密钥进行版本管理,使我们可以根据我们的安全策略定期更换密钥的同时,也能兼容旧密钥签发的 JWT——在他们过期之前一直是可用的状态,过期之后便使用新的密钥签名。

JWT 标准在 Header 中通过 kid 字段规定了生成令牌签名所使用的签名密钥 ID, DOF JWT 实现利用了这个字段名来实现密钥版本管理,其中 kid 既可以是一个整数,也可以是一个字符串,用于在密钥配置文件中查找对应版本的签名密钥。

环境识别

如果你还有在地区 A 某个 Web 浏览器登录的令牌只能在地区 A 的这个 Web 浏览器内使用,在地区 B 的客户端登录的令牌只能在地区 B 的通过客户端使用,类似这样的需求,那么环境识别就能派上用场了。

DOF JWT 的环境识别特性可以让你在生成 JWT 的请求中,对请求的环境关键上下文字段进行 HASH,当你切换环境时,HASH 值会变,JWT 校验就会不通过。

记住我

TODO

自动续期

TODO

results matching ""

    No results matching ""