JWT(理论篇)

前言

互联网服务离不身份验证,JWT一种跨域身份验证解决方案,全称JSON WEB TOKEN,在web中通过json格式组装数据传输的一种token。

JWT的特点

  • 无状态(token签发后服务器不会保留任何用户登录信息)
  • 可扩展 (token仅存储在客户端完全无状态,因此可以负载均衡传输到任何服务器)
  • 通用性 (jwt是一串加密的字符,只要能转输字符就能使用jwt)

JWT对比SESSION

jwt-png

session的工作方式

  1. 前端输入用户名密码通过http请求发送给服务器
  2. 服务器验证通过,在服务器本地保存一个session(里面写入了业务数据)
  3. 服务器返回一个session_id给前端,前端自动写入cookie
  4. 前端登录成功,下次发请求前端会自动带上有session_id的cookie
  5. 服务器拿到session_id去本地找到对应的session读取里面的数据

jwt的工作方式

  1. 前端输入用户名密码通过http请求发送给服务器
  2. 服务器验证通过,将业务数据(如用户的id,称昵等)通过base64进行编码生成token
  3. 服务器将token写入http请求响应中返回给前端
  4. 前端拿到token存储在本地,下次发请求时将token放在http请求中带给服务器
  5. 服务器收到token通过base64解密拿到业务数据
  6. 服务器进行签名对比,签名一致证明用户合法

 

明显的区别jwt存储在客户端,session存储在服务器所以不利于分布式多台服务器负载均衡(因为用户登录后只在一台服务器存储了session别的服务器上没有),需且还会占用服务器存储空间。

还有个硬伤session是依赖cookie传输session_id的,但有些客户端是不支持cookie的比如说小程序。

jwt长什么样?

如图jwt是一串由三个点分隔开的加密字符串,由 header(头部)、payload(负载)、signature(签名)组成。

header

header由一个json对象组成,里面包函两个字段:

{
  "alg": "HS256", // 表示token的类型是jwt
  "typ": "JWT" // 表示使用的签名算法是HS256
}

将这部分由base64编码组成jwt字符串的第一部分。

payload

payload也是由一个json组成,里面用来存放业务数据通常是用户的基本信息(用户id,用户权限)和一些用来描述令牌的数据(令牌的颁发时间,令牌的过期时间)。

jwt官方推荐了七个字段,但这不是必须的:

  • iss (issuer):签发人
  • exp (expiration time):过期时间
  • sub (subject):主题
  • aud (audience):受众
  • nbf (Not Before):生效时间
  • iat (Issued At):签发时间
  • jti (JWT ID):编号

我经常定义这几个字段:

{
  "uid": "HS256", // 用户的id
  "nickname": "bwx", // 用户的昵称
  "exp": "1608703180085" // 令牌的过期时间
}

将这部分由base64编码组成jwt字符串的第二部分。


注意:不要在JWT的payload或header中放置敏感信息,只需存储用户的唯一标识即可,因为payload、header部分只是通过base64将json格式的数据编码成字符串方便传输,客户端拿到这串字符编码回去即可看到里面的内容。

signature

signature是对header和payload进行签名防止数据被篡改。

签名的过程是将base64编码后的header、base64编码后的playload以及密钥secret通过header中指定的算法进行计算得到。

这个secret不能泄漏只能服务器知道。
 
因为如果客户端拿到token进行base64解码,然后修改前两部分的数据(header、payload)再用base64编码回去发送给服务端,服务拿到header、payload两部分加上secret加密得到signature,跟客户端传入的signature做对比发现不一致,因此就能得知数据被篡改了。

上图可看到jwt的组织结构。

token的过期时间设置多久好?

  • 面对极度敏感的信息,如钱或银行数据,那就根本不要在本地存放Token,只存放在内存中。这样,随着App关闭,Token也就没有了。

  • 此外,将Token的时限设置成较短的时间(如1小时)。

  • 对于那些虽然敏感但跟钱没关系,如健身App的进度,这个时间可以设置得长一点,如个月。

  • 对于像游戏或社交类App,时间可以更长些,半年或1年。

token泄漏别人可以冒充我登录吗?

别人拿到你的token通过http请求发送给服务器是可以冒充你的,但我们可以在服务器写一些逻辑预防这些:

  1. 在服务器为用户建立一个常用ip表存储用户常用ip,当你的token被盗取防问服务器的ip不再常用ip表中就让用户重新授权,有点类似于QQ的异地登录。

  2. 颁发令牌时将用用户的ip存储到jwtpayload中,当你的token被盗取防问服务器的ip跟payload中的ip不一至就让用户重新授权。

  3. token过期时间设置的短一些。

参考链接

http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html by 阮一峰

https://www.cnblogs.com/cjsblog/p/9277677.html by 废物大师兄

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注