zoukankan      html  css  js  c++  java
  • 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验证的流程完毕。

  • 相关阅读:
    Java-判断一个数是不是素数
    Sublime快捷键
    python
    全排列
    python
    python
    OpenCV 实现图像结构相似度算法 (SSIM 算法)
    C++
    C++
    NFA 转 DFA
  • 原文地址:https://www.cnblogs.com/Mr-Kahn/p/13151738.html
Copyright © 2011-2022 走看看