JWT的Token认证机制

1,498 阅读3分钟

JWT主要由三部分组成

1.头部header

主要由两部分信息组成

声明类型 JWT

声明加密算法,如:HMAC、SHA256、HS256

下面就是一个完整的头部信息:

{

"typ": "JWT"

"alg": "HS256"

}

Base64进行编码后的字符串如下:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

 

2.载荷 payload

主要有三部分组成:标准中注册声明、公共的声明、私有声明

标准中组成声明

iss:jwt签发者,是否使用是可选的;

sub:jwt所面向的用户,是否使用是可选的;

aud:接收jwt的一方,是否使用是可选的;

exp:jwt的过期时间,这个过期时间必须大于签发时间,Unix时间戳,是否使用是可选的;

nbf:定义在什么时间之前,该token都是不可用的

iat:jwt的签发时间,是否使用是可选的;

jti:jwt的唯一身份标识,避免重复

如:

{

  "iss": 'jwt'

  "sub": "h3yun.com",

  "exp": "16386018625",

  "iat": "1638605625",

  "jti": "e983544312y4343432143rweqrr",

}

Base64 编码后字符串如下

JTdCJTBBJTIwJTIwJTIyaXNzJTIyJTNBJTIwJTI3and0JTI3JTBBJTIwJTIwJTIyc3ViJTIyJTNBJTIwJTIyaDN5dW4uY29tJTIyJTJDJTBBJTIwJTIwJTIyZXhwJTIyJTNBJTIwJTIyMTYzODYwMTg2MjUlMjIlMkMlMEElMjAlMjAlMjJpYXQlMjIlM0ElMjAlMjIxNjM4NjA1NjI1JTJDJTBBJTIwJTIwJTIyanRpJTIyJTNBJTIwJTIyZTk4MzU0NDMxMnk0MzQzNDMyMTQzcndlcXJyJTIyJTJDJTBBJTdEJTBB

3.签名 signature

讲上面 header 和 payload base64编码之后的拼接起来 :

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.JTdCJTBBJTIwJTIwJTIyaXNzJTIyJTNBJTIwJTI3and0JTI3JTBBJTIwJTIwJTIyc3ViJTIyJTNBJTIwJTIyaDN5dW4uY29tJTIyJTJDJTBBJTIwJTIwJTIyZXhwJTIyJTNBJTIwJTIyMTYzODYwMTg2MjUlMjIlMkMlMEElMjAlMjAlMjJpYXQlMjIlM0ElMjAlMjIxNjM4NjA1NjI1JTJDJTBBJTIwJTIwJTIyanRpJTIyJTNBJTIwJTIyZTk4MzU0NDMxMnk0MzQzNDMyMTQzcndlcXJyJTIyJTJDJTBBJTdEJTBB

以 HS256 为例

signature = HS256( 上面拼接起来的字符串. xxxx); // xxx 表示 一串随机的字符

最后 把上面三部分连接起来就是我们需要的JWT Token了

整个校验流程是:

1. 用户在登录页,输入用户名和密码,进行登录

2. 服务器对登录用户进行认证,如果认证通过,根据用户的信息和JWT的生成规则生成JWT Token

3. 服务器将该Token字符串返回

4. 客户端得到Token信息,将Token存储在cookie中。

5. 当用户请求服务器API时,在请求的Header中加入 Authorization:Token。

6. 服务端对此Token进行校验,如果合法就解析其中内容,根据其拥有的权限和自己的业务逻辑给出响应结果,如果不通过,返回HTTP 401,提示用户权限。通过就执行前端回调进入系统

前端请求是将 token 放入到header里边 Authorization

第一种:

proxy.js 文件

const proxyAjax = () => {
  if (!XMLHttpRequest) {
    return;
  }

  const nativeAjaxSend = XMLHttpRequest.prototype.send;

  XMLHttpRequest.prototype.send = function (...args) {

    const oldCb = this.onreadystatechange;

    const token = getToken();

    if (token) {

      this.setRequestHeader('authorization', `Bearer ${token}`);

    }

    this.onreadystatechange = (...innerArgs) => {

      if (this.readyState === 4) {

        switch (this.status) {

          case 401:

            // token 失效, 清除cookie中token, 跳转到登录页

            clearAuthorization(); //自己实现清除方法,这里不展开

            //to do             

            break;

          default

            break;

        }

      }

      oldCb && oldCb.apply(this, innerArgs);

    };

    return nativeAjaxSend.apply(this, args);

  };

};

export default proxyAjax();

在项目中入口文件引入即可,如果是vue 多页面就每个页面main.js都需要引入

第二种:

如果是项目中引入请求的 axios 或fetch 改,以axios为例

axios.interceptors.request.use((config) => {

  config.headers.authorization=`Bearer ${token}`;

……

}, error => {

  Promise.reject(error);

});

第三种: 每一个接口去设置 Authorization


fetch('xxx', { //接口地址

  headers: {

    'Authorization': 'Bearer ' + token
  }
})

显然不如上面好

 

JWT Token机制优缺点

优点:

不需要储存在服务器的session中,更容易扩展服务器

由于用户信息可以放入token中,所以可以少了一次数据库 / 缓存的查询操作,有更好的性能

不需要预防CSRF的攻击

缺点:

token一经泄露或者被盗取,将会暴露该用户

建议

设置token的过期时效时间,不宜过长; 协议使用https

安全较高的接口,二次验证保险 如手机验证码,支付密码等