通俗易懂讲解Json Web Token (JWT)

前言

之前只是了解JWT是对cookie和session的一种升级方案,在前后分离的项目中用的比较多,今天突然好奇,它到底怎么解决session共享的问题的,觉得大概明白后,总结了一下相关知识。

基于session认证所显露的问题

session数据默认是保存在服务器内存中的,而随着认证用户的增多,服务端的开销会明显增大。

因为session是保存在服务器内存中的,在分布式的应用上,不能保证每次都请求到同一台服务器,相应的限制了负载均衡的能力,只能通过服务器之间的session共享解决问题。

session是基于cookie来进行用户识别的, cookie如果被截获,用户就会很容易受到**跨站请求伪造(CSRF)**的攻击。

组成

Token由三部分组成:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.UQmqAUhUrpDVV2ST7mZKyLTomVfg7sYkEjmdDI5XF8Q

第一部分为头部(header),其中包含了签名的加密算法

第二部分为载荷(payload, 类似于飞机上承载的物品),用来保存用户的相关信息

第三部分是签名(signature),用来验证token是否被篡改过

header

jwt的头部承载两部分信息:

  • 声明类型,这里是jwt
  • 声明签名的加密算法 通常直接使用 HMAC SHA256

完整的头部就像下面这样的JSON:

{  'typ': 'JWT',  'alg': 'HS256'}

然后将头部进行base64加密(该加密是可以对称解密的),构成了第一部分

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

playload

包含三个部分:

  • 标准中注册的声明
  • 公共的声明
  • 私有的声明

标准中注册的声明 (建议但不强制使用) :

  • iss: jwt签发者
  • sub: jwt所面向的用户
  • aud: 接收jwt的一方
  • exp: jwt的过期时间,这个过期时间必须要大于签发时间
  • nbf: 定义在什么时间之前,该jwt都是不可用的.
  • iat: jwt的签发时间
  • jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。

公共的声明 :

公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息。但不建议添加敏感信息,因为该部分在客户端可解密。

私有的声明 :

私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。

payload示例:

{  "sub": "1234567890",  "name": "John Doe",  "admin": true}

然后将其进行base64加密,得到Jwt的第二部分

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9

signature

jwt的第三部分token签名,它通过base64加密后的header和payload生成。

服务端将base64加密后的header和payload使用.连接组成一个字符串(头部在前),然后通过header中声明的签名加密方式使用secret密钥加密,就构成了jwt的第三部分。

如果header和payload的内容被修改过,生成的签名就会是不同的(可以理解成不同内容的哈希值不一样),从而达到判断token是否是被篡改过的效果。

签名示例:

UQmqAUhUrpDVV2ST7mZKyLTomVfg7sYkEjmdDI5XF8Q

密钥secret是保存在服务端的,服务端会根据这个密钥进行生成token和验证,需要保护好,不能泄漏。

验证过程

服务器应用在接受到JWT后,会首先对头部和载荷的内容用同一算法再次进行签名。

如果服务器应用对头部和载荷再次以同样方法签名之后发现,自己计算出来的签名和接受到的签名不一样,那么就说明这个Token的内容被篡改过,否则就完成了验证。

那么服务器应用是怎么知道我们用的是哪一种算法进行的签名的呢?JWT的头部中已经用alg字段指明了我们的签名加密算法了。

基于token的鉴权机制

  • 用户使用用户名密码来请求服务器
  • 服务器进行验证用户的信息
  • 服务器通过验证发送给用户一个token
  • 客户端存储token,并在每次请求时附送上这个token值
  • 服务端验证token值,并返回数据

优点

  • 支持跨域访问: Cookie是不允许垮域访问的,Token机制不基于Cookie实现,可以跨域访问。
  • 服务端无状态,可扩展性好: Token机制在服务端不需要存储session信息,因为Token 自身包含了所有登录用户的信息,服务端只需要进行token验证即可。
  • 更安全:Token不基于Cookie实现,不会出现Cookie劫持所导致的安全问题。

总结

作者:scluis 原文地址:https://blog.csdn.net/weixin_42619772/article/details/123426130

%s 个评论

要回复文章请先登录注册