JWT使用与原理

一、简介

JSON Web令牌是一种开放的、行业标准的RFC 7519方法,用于安全地表示双方之间的声明。(来自官网翻译)

特点:

  • 无状态:无需对会话进行额外的存储方案选择,适合分布式情景下使用
  • 非对称加密:通过密钥进行加密前后比较,防止暴力破解
  • 携带信息:通过负载携带部分常使用的信息,减少后端与DB的交互

二、使用流程

  • 使用用户名与密码请求服务器
  • 服务器验证用户信息
  • 通过验证后,根据选定的加密方法、负载、密钥,产生一个token并返回给客户端
  • 客户端接收到token后进行存储,并在后续的请求中携带该token
  • 服务端在处理请求之前,对该token进行获取与验证,如果无误,继续处理请求;如果验证失败,则中止请求并返回特定信息

三、组成结构

通过英文句号.连接,由三部分组成:header(头部)payload(负载)signature(签证)

3.1 header(头部)

头部的原始信息类似下面形式的JSON:

{
      "typ": 'JWT',            //类型申明,
      "alg": "HS256"            //加密算法
}

上面的信息通过base64加密后,得到token中的第一个字符,即header

3.2 payload(负载)

负载也是由JSON信息通过base64加密得到的,此处可以添加自定义参数,如用户名、昵称等经常需要使用的信息(注意base64为对称加密,所以不要存放敏感信息于此)。

负载也有标准字段,常见的有如下:

  • iss: 签发者
  • iat: 签发时间(如无定义则为现在机器时间)
  • exp: 过期时间,这个过期时间必须要大于签发时间

nodejs中的jsonwebtoken模块通过sign方法进行签名时,对于iatexp的使用操作如下:

/**
 * ./sign.js
*/
module.exports = function (payload, secretOrPrivateKey, options, callback) {
      ......
      var timestamp = payload.iat || Math.floor(Date.now() / 1000);            //iat无定义时,默认当前时间(秒)
      ......
      if (typeof options.expiresIn !== 'undefined' && typeof payload === 'object') {
            try {
                  payload.exp = timespan(options.expiresIn, timestamp);
            }catch (err) {
                  return failure(err);
            }
            if (typeof payload.exp === 'undefined') {
                  return failure(new Error('"expiresIn" should be a number of seconds or string representing a timespan eg: "1d", "20h", 60'));
            }
      }
      ......
}

上面代码中的timespan函数引用同项目中的文件./lib/timespan.js :

可以看到,如果expiresIn如果为string类型的数字,如"60",则会当作秒数,与iat一起计算得到过期时间;如果expiresInNumber类型,则会当作毫秒数(millisecond)计算过期时间。所以就有了官方Readme中的这句话:

3.3 签证(signature)

通过前面经过base64加密后形成的headerpayload,以及密钥secret与编码方式(默认utf-8)进行非对称加密:

该处引用了jws包,其函数定义的地方如下:

jwsSign函数定义如下

由上述代码可以了解到,生成token的步骤是:

  1. headerpayload分别进行base64加密,将两个结果用点号.连接,得到securedInput
  2. 通过定义alg所对应的加密方法,利用密钥secretOrKeysecuredInput进行非对称加密得到signature
  3. securedInputsignature再次通过点号.进行连接,即将headerpayloadsignature进行连接

四、验证原理

理论上,知道了token的生成方法,大致也就能反推到其验证的原理:

  • 先将headerpayload通过非对称加密后,得到新的signature,与token中的原始signature相比较,如果不等,返回无效token
  • 如果相等,通过base64解密,验证payload中的过期时间等信息,如果存在过期等异常情况,则也返回无效token(只是与前面无效token的返回信息不同罢了)
  • 如果一切正常,返回payload等信息

为了证明我们猜想的正确性,还是通过观察jsonwebtoken源码来验证,这里就不一张一张的贴图了,将相关代码整合在一起的情况如下:

由上面的过程可以看到,验证的原理基本如猜想一样,验证后,返回解析后的payload等信息:

自此,token验证的流程完毕。

posted @ 2020-06-18 11:09  Mr_Kahn  阅读(461)  评论(0编辑  收藏  举报