基于 JWT + Refresh Token 的用户认证实践
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于 JWT + Refresh Token 的用户认证实践相关的知识,希望对你有一定的参考价值。
参考技术A HTTP 是一个无状态的协议,一次请求结束后,下次在发送服务器就不知道这个请求是谁发来的了(同一个 IP 不代表同一个用户),在 Web 应用中,用户的认证和鉴权是非常重要的一环,实践中有多种可用方案,并且各有千秋。基于 Session 的会话管理
在 Web 应用发展的初期,大部分采用基于 Session 的会话管理方式,逻辑如下。
基于 Session 的方式存在多种问题。
基于 Token 的会话管理
鉴于基于 Session 的会话管理方式存在上述多个缺点,无状态的基于 Token 的会话管理方式诞生了,所谓无状态,就是服务端不再存储信息,甚至是不再存储 Session,逻辑如下。
基于 Token 的会话管理方式有效解决了基于 Session 的会话管理方式带来的问题。
JWT 介绍
JWT 是 JSON Web Token 的缩写,JWT 本身没有定义任何技术实现,它只是定义了一种基于 Token 的会话管理的规则,涵盖 Token 需要包含的标准内容和 Token 的生成过程。
一个 JWT Token 长这样。
仔细辨别会发现它由 A.B.C 三部分组成,这三部分依次是头部(Header)、负载(Payload)、签名(Signature),头部和负载以 JSON 形式存在,这就是 JWT 中的 JSON,三部分的内容都分别单独经过了 Base64 编码,以 . 拼接成一个 JWT Token。
JWT 的 Header 中存储了所使用的加密算法和 Token 类型。
Payload 是负载,JWT 规范规定了一些字段,并推荐使用,开发者也可以自己指定字段和内容,例如下面的内容。
需要注意的是,Payload的内容只经过了 Base64 编码,对客户端来说当于明文存储,所以不要放置敏感信息。
Signature 部分用来验证 JWT Token 是否被篡改,所以这部分会使用一个 Secret 将前两部分加密,逻辑如下。
JWT 优势 & 问题
JWT 拥有基于 Token 的会话管理方式所拥有的一切优势,不依赖 Cookie,使得其可以防止 CSRF 攻击,也能在禁用 Cookie 的浏览器环境中正常运行。
而 JWT 的最大优势是服务端不再需要存储 Session,使得服务端认证鉴权业务可以方便扩展,避免存储 Session 所需要引入的 Redis 等组件,降低了系统架构复杂度。但这也是 JWT 最大的劣势,由于有效期存储在 Token 中,JWT Token 一旦签发,就会在有效期内一直可用,无法在服务端废止,当用户进行登出操作,只能依赖客户端删除掉本地存储的 JWT Token,如果需要禁用用户,单纯使用 JWT 就无法做到了。
基于 JWT 的实践
既然 JWT 依然存在诸多问题,甚至无法满足一些业务上的需求,但是我们依然可以基于 JWT 在实践中进行一些改进,来形成一个折中的方案,毕竟,在用户会话管理场景下,没有银弹。
前面讲的 Token,都是 Access Token,也就是访问资源接口时所需要的 Token,还有另外一种 Token,Refresh Token,通常情况下,Refresh Token 的有效期会比较长,而 Access Token 的有效期比较短,当 Access Token 由于过期而失效时,使用 Refresh Token 就可以获取到新的 Access Token,如果 Refresh Token 也失效了,用户就只能重新登录了。
在 JWT 的实践中,引入 Refresh Token,将会话管理流程改进如下。
将生成的 Refresh Token 以及过期时间存储在服务端的数据库中,由于 Refresh Token 不会在客户端请求业务接口时验证,只有在申请新的 Access Token 时才会验证,所以将 Refresh Token 存储在数据库中,不会对业务接口的响应时间造成影响,也不需要像 Session 一样一直保持在内存中以应对大量的请求。
上述的架构,提供了服务端禁用用户 Token 的方式,当用户需要登出或禁用用户时,只需要将服务端的 Refresh Token 禁用或删除,用户就会在 Access Token 过期后,由于无法获取到新的 Access Token 而再也无法访问需要认证的接口。这样的方式虽然会有一定的窗口期(取决于 Access Token 的失效时间),但是结合用户登出时客户端删除 Access Token 的操作,基本上可以适应常规情况下对用户认证鉴权的精度要求。
总结
JWT 的使用,提高了开发者开发用户认证鉴权功能的效率,降低了系统架构复杂度,避免了大量的数据库和缓存查询,降低了业务接口的响应延迟。然而 JWT 的这些优点也增加了 Token 管理上的难度,通过引入 Refresh Token,既能继续使用 JWT 所带来的优势,又能使得 Token 管理的精度符合业务的需求。
作者:simpleapples
链接:https://www.jianshu.com/p/25ab2f456904
Refresh-Token (JWT) 如何避免中间人攻击?
【中文标题】Refresh-Token (JWT) 如何避免中间人攻击?【英文标题】:How do Refresh-Token (JWT) avoid to man-of-the middle attack? 【发布时间】:2020-05-12 00:39:03 【问题描述】:我最近使用 DotNet 核心身份实现了 JWT 身份验证。
我知道要减少身份验证的次数以获取 Access-Token(当它在短时间内过期以提高安全性时)我们使用 Refresh-Token 来更新 access-token 而不是重新身份验证。
我认为如果中间人试图窃取 Refresh-Token 以获取新的 Access-Token 并发出请求(劫持令牌),系统如何找到它并拒绝该请求?
我的意思是,如果 JWT 被某人盗用冒充,服务器识别它并拒绝它,是否有解决方案? (我知道 SSL 可以提供帮助,但我正在考虑其他方式。例如,按时间和 Ip 加密 JWT 或 ....?)
【问题讨论】:
【参考方案1】:假设您在服务器和客户端之间使用两种方式的 SSL,那么您的担忧主要是没有实际意义的。原因是任何中间人,如果他找到拦截的方法,甚至都不知道 JWT 从哪里开始和结束。相反,他只会被一些编码的混乱所困。假设,如果有人持有 JWT,那么是的,他可能能够冒充您的一个用户。这与偷信用卡然后伪装成所有者没有什么不同。但是,由于 SSL,这种情况发生的可能性很小。
【讨论】:
你的意思是不需要担心客户端用户内部的JWT劫持? 当然这是一个问题,因此如果你在谈论一个网站,你不应该将 JWT 存储到 cookie 或本地存储等。但是你强调的问题不仅限于 JWT ,对于所有数据都是一个问题。 @Mohammad 如果您真的担心 JWT 被劫持,请遵循银行和其他类似安全网站使用的模式。他们发出的所有令牌(身份验证和刷新)都非常短暂,最多几分钟。因此,现在即使有人劫持了令牌,他们也必须非常快速地获取和使用它,从而进一步降低您的风险(除了 SSL 已经为您提供的保护之外)。 是的,我想是的,我发现使用 SSL 并减少 Access-Token 的过期时间并将 JWT 存储在浏览器中的安全位置,我们可以将模拟的风险降低到接近 0%。跨度>以上是关于基于 JWT + Refresh Token 的用户认证实践的主要内容,如果未能解决你的问题,请参考以下文章
如何以及为啥使用 refresh_token 处理 jwt 令牌过期,还有另一种选择吗? [关闭]
jwt中为什么用refresh_token去刷新access_token,直接把access_token的有效期设置长一点不行吗?
如何使用 JWT 在 Spring Boot 中获取 Refresh Token