用大白话讲明白JWT

JWT,是JSON Web Token的缩写,目前最流行的跨域认证解决方案。

为什么需要JWT?

一般的互联网用户认证流程如下:

  1. 用户向服务器发送用户名和密码。
  2. 服务器验证通过后,在当前对话(session)里面保存相关数据,比如用户角色、登录时间等等。
  3. 服务器向用户返回一个 session_id,写入用户的 Cookie。
  4. 用户随后的每一次请求,都会通过 Cookie,将 session_id 传回服务器。
  5. 服务器收到 session_id,找到前期保存的数据,由此得知用户的身份。

这就是经典的cookie-session认证模式,cookie保存在客户端,持有session-id,而session保存在服务端,持有用户信息和权限、过期时间等信息。

这种模式简洁易用,还能保证信息安全。

但是随着架构更新成服务器集群跨域的服务导向架构,就要求实现session共享,否则不能实现session共享。一般来说,能够通过中间件实现session共享,比如redis。

举例来说,某系统有两个后端服务,都是集群部署,分别为服务A和服务B,用户在A服务登录之后,携带session-id请求B,要求用户能够通过B的登录验证,并且能获取用户信息。
大家都知道,session默认是存储的服务端的硬盘中,上面的场景中,用户登录的session应该会存储在服务集群A的某个节点上,那么用户访问任何其他的节点或服务都要重新登录。
简易架构图
最常见的解决方案就是利用中间件存储session。如上图中,若将session存储在redis中,那么用户登录之后,每个服务节点都能通过session-id查询到session,实现单点登录。

那么这种cookie-session模式有什么缺点呢?

  1. 客户端禁用cookie就会失效
  2. 跨域可能会导致cookie丢失
  3. 必须要有统一的中间件
  4. 中间件如果挂了,登录就会失效

优化方案

  1. 弃用cookie,直接将用户token存放在request header中,用户信息以token为key存放在redis
  2. 服务器索性不保存session数据了,直接将用户token和用户信息全都存在request header中,JWT就是此方案的代表

JWT的原理

怎么实现将用户信息存放在客户端,还能实现用户登录认证和权限认证?
我们可以将用户信息和用户权限和用户认证时间放一起生成一个json,如下

{
  "姓名": "张三",
  "角色": "管理员",
  "到期时间": "2024年12月1日0点0分"
}

然后如果将这个字符串放在请求头中,那么服务端每次接收到请求都能知道用户信息和是否已登录等。
这样做的好处是服务器是无状态的,扩展性非常好。
但是请求头必须经过编码和网络传输,需要考虑乱码和URLEncode等问题。
所以我们要将上面的字符串使用Base64URL进行编码,规避这些问题。

新问题又来了,用户信息在客户端被篡改了怎么办?
我们再加一道签名(一种信息安全技术,此处不展开),防止信息篡改。

最终,上面的JSON经过这样魔改之后,就是所谓的JWT!它最终长这样:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyLlp5PlkI0iOiLlvKDkuIkiLCLop5LoibIiOiLnrqHnkIblkZgiLCLliLDmnJ_ml7bpl7QiOiIyMDI05bm0MTLmnIgx5pelMOeCuTDliIYifQ.fvBo5i2wXeYufnUQGLaJvtY6GdcqRhTgA5kc5S8HqLU

总结一下,JWT就是一串经过签名和编码的json对象,用户登录后由服务端生成,一般通过request header传输,轻松实现在不同平台和系统间信息交换和认证。

JWT官网: [https://jwt.io/]

JWT结构

JWT 有三个部分,依次如下。

Header(头部)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

怪力乌龟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值