vue axios 刷新token 刷新jwt js刷新token http刷新token

前言 在互联网的登陆系统中一般有session cookie 和 jwt token来进行验证用户是否登录的.下面来说一下关于 jwt的坑:

1.首先登录成功的返回,其中jwt的有效期为2小时,refreshJwt的有效期为30天如下:

2.保存jwt 和refreshJwt 在cookie中,当然这里不一定要保存在cookie中,也可以保存在别的地方.这里以cookie为例子:

 3.核心思路:当jwt过期时(超过了2小时),调用后端接口会返回401的状态码(这个时候代表jwt已经过期了,需要刷新了),再拦截器中拦截响应的数据,这个时候就需要拿refreshJwt去调用后端的刷新接口,把获取到的最新jwt覆盖掉本地的jwt和refreshJwt,然后再次进行刚才的请求,并且把获取到的数据,从响应拦截器中返回回去.

步骤大概如此: 前端发起ajax请求 => 后端发现jwt已经过期,返回401状态码 => 前端拦截响应数据,并发起刷新token的请求 => 拿到最新的jwt和refresh,保存到本地 => 拿到最新的jwt去进行刚刚未请求成功的接口 => 获取到刚刚请求的结果,覆盖第一次请求失败(状态码为401)的响应数据 => 返回第二次请求的结果.   

另一种情况就是:前端发起ajax请求 => 后端发现jwt已经过期,返回401状态码 => 前端拦截响应数据,并发起刷新token的请求 =>后端返回了410的状态码(这个时候代表refreshJwt也过期了,需要进行重新登录了) => 真正的过期了,需要跳转到登录界面.  

这样刷新token是在用户无感的情况下进行操作的.

下面进行贴代码了:

此拦截器模块为http,封装的步骤参考:https://blog.csdn.net/qq_33270001/article/details/86612528  注:原来的http模块中并未封装refreshJwt的操作.

3. 新建一个refreshToken.js的文件:

看核心操作就是,util.getCookie(`REFRESHJWT-COLLECTOR`); 这些都是封装来操作cookie的工具.无需重点关注

import axios from 'axios';
import router from '@/router/index';
import util from '@/common/method/util';
import { API_COMMON } from './models/types';
export default async() => {
    const refreshToken = util.getCookie(`REFRESHJWT-COLLECTOR`);
    try {
        const { code, data } = await axios.post(`${API_COMMON}/refreshJwt`, { refreshJwt: refreshToken });
        if (code == 410) {
            return router.replace({ path: '/login', query: { redirect: router.currentRoute.fullPath } });
        } else {
            const { jwt, refreshJwt } = data;
            if (jwt && refreshJwt) {
                util.setCookie(`TOKEN-COLLECTOR`, jwt); //jwt
                util.setCookie(`REFRESHJWT-COLLECTOR`, refreshJwt); //刷新token
            }
        }
        return { code, data };
    } catch (error) {
        console.log(error);
    }
};

4. 拦截器配置如下:

/***
 * Created by Simple on 2018/1/14 0014.
 * Http请求控制器模块
 */

import axios from 'axios';
import router from '@/router/index';
import conf from '@/common/base/config';
import util from '@/common/method/util';
import { Loading, Message } from 'element-ui';
import refreshToken from './refreshToken';
// axios 配置
axios.defaults.timeout = 1000 * 60 * 5;
axios.defaults.baseURL = process.env.NODE_ENV === 'production' ? conf.productionUrl : conf.devUrl;
// 配置通用请求动画
let loading = null;
let isLock = true;

/**
 * 通用请求拦截配置
 * @param {*} config
 */
const axiosConf = (config) => {
    config.headers.Authorization = util.getCookie(`TOKEN-COLLECTOR`);
    loading = Loading.service({
        lock: true,
        text: '拼命加载中...',
        background: 'rgba(255, 255, 255, .1)'
    });
    return config;
};
axios.interceptors.request.use(axiosConf, err => {
    if (loading) loading.close();
    return Promise.reject(err);
});
// http response 拦截器
axios.interceptors.response.use(async(response) => {
    let data = {};
    if (response && response.data) {
        let code = Number(response.code || response.data.code);
        if (code === 401) { // 401 清除token信息并跳转到登录页面
            const refreshJwt = util.getCookie(`REFRESHJWT-COLLECTOR`);
            if ((refreshJwt != 'undefined' && refreshJwt) && isLock) {
                await refreshToken(response);
                isLock = false; //这里防止并发的时候造成死循环,所以要加锁
                //刷新完成,继续之前的请求
                response.config.headers.Authorization = util.getCookie(`TOKEN-COLLECTOR`);
                const result = await axios.request(axiosConf(response.config));
                if (result) {
                    data = result;
                    isLock = true;
                }
            } else {
                Message.error(response.data && response.data.msg || `身份过期,请重新登录!`);
                if (router.currentRoute.path != '/login') {
                    setTimeout(() => {
                        router.replace({ path: '/login', query: { redirect: router.currentRoute.fullPath } });
                    }, 1200);
                }
            }
        } else if (code === 200) {
            data = response.data;
        } else if (code === 403) { //无权限
            Message.error(`无权访问!`);
            router.replace({ name: '/403', query: { redirect: router.currentRoute.fullPath } });
        } else if (code === 410) {
            Message.error(`身份过期,请重新登录!`);
            setTimeout(() => {
                router.replace({ path: '/login', query: { redirect: router.currentRoute.fullPath } });
            }, 1200);
        } else {
            Message.error(response.data && response.data.msg || '网络连接出错!请稍后刷新重试!');
        }
    }
    if (loading) loading.close();
    return data;
}, (error) => {
    console.log(`object`, error);
    if (loading) loading.close();
    Message.error('哎呀~ (ಥ﹏ಥ)网络又开小差了,请稍后刷新重试!');
    return Promise.reject(error.response.data);
});

export default axios;

5.  操作演示:

已经过期了,需要进行刷新操作

进行刷新覆盖操作 

 

重新进行请求,并覆盖掉原来的

大功告成,小生的刷新token思路如此,如阁下有更好的思路,方便分享,请留言哦,刷新token已经可以了.有问题的小伙伴请求留言.

发布了71 篇原创文章 · 获赞 47 · 访问量 10万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览