微信小程序自动刷新token,无感刷新token

        小程序登录开发通常是调用wx.login获取code,然后发送到后台,后台请求微信拿到用户openId,然后根据openId查询用户,有就走登录流程然后返回token,没有则创建用户之后走登录流程然后返回token,也就是都需要返回一个有时效性的token给小程序端,来保持登录状态,并且后续请求都需要token来验证用户。

        那么就有一个问题,就是token的时效性,token过期,后台返回认证授权失败,那么怎么做到无感刷新token,让用户即使token过期了自动刷新token呢?经过查询跟实践,我封装了一个请求类。

        思路大致是根据后台返回的状态,如果返回的是授权失败,那么就会保存当前请求,调用刷新token的请求,成功之后再次发起之前保存的请求,这样就可以达到用户无感的刷新token。

        具体封装类api.js如下,本次代码采用uniapp框架开发,实际项目中每次发起后台请求只需要调用req方法即可做到无感刷新token:

微信小程序自动刷新token,无感刷新token,封装的api工具类icon-default.png?t=N7T8https://download.csdn.net/download/weixin_47315082/88041695

//定义token在Storage中的key值
var tokenKey = "token";
//constant.js中定义请求url地址,例如baseUrl:http://192.168.0.5/api
import constant from './constant.js'

export function logout() {
    //退出时删除token
    uni.removeStorageSync('token')
}

//定义登录方法,传入wx.login获取到的code
export function login(data) {
    let header = {};
    header['Content-type'] =
        'application/json;charset=utf-8';
    return new Promise((resolve, reject) => {
        uni.request({
            //调动后台自定义微信登录方法,获取token
            url: constant.baseUrl + "/wxLogin",
            data: data,
            header: header,
            method: 'POST',
            success(res) {
                try {
                    if (res.statusCode === 200 && res.data.code === 200 && res.data.data.token && res.data.data.token !== "false") {
                        //获取成功,保存token到Storage中
                        uni.setStorageSync(tokenKey, res.data.data.token);
                        resolve(res.data)
                    } else {
                        //获取成功,删除当前Storage中的token
                        uni.removeStorageSync('token')
                        reject(res)
                    }
                } catch (e) {
                    console.log("res.data");
                    //请求失败
                    reject(e)
                }
            },
            fail(err) {
                console.log('request', err)
                //请求失败
                reject(err)
            }
        })
    })
}

//自定义通用请求类
export function req(config) {
    let method = config.method || 'GET';
    let url = config.url || "";
    let data = config.data || {};
    let header = config.header || {};
    //关键点:定义一个callback变量,来保存需要刷新token之后再次发起的请求
    let callback = config.callback;
    header['Content-type'] = config.contentType || (method == 'POST_PARAMS' ? 'application/x-www-form-urlencoded' :
        'application/json;charset=utf-8');
    //获取当前Storage中的token值
    let tokenValue = uni.getStorageSync(tokenKey) || ' ';
    //这里自定义请求,如果请求url中包含"/f/",说明该请求不需要验证token,否则就需要,将token值存入请求头中供后台验证,'Authorization'为后台自定义token的请求头key值
    if (url.indexOf("/f/") < 0) {
        header['Authorization'] = tokenValue;
    }
    return new Promise((resolve, reject) => {
        //发起请求
        uni.request({
            url: constant.baseUrl + url,
            data: data,
            header: header,
            method: method,
            success(res) {
                //如果callback存在,说明是需要再次发起请求,直接调用callback即可
                if (callback) {
                    return callback(res.data);
                }
                if (res.statusCode === 401 || res.data.code === 401) {
                    //如果返回401,说明当前token认证授权失败,也就是说需要刷新token
                    if (tokenValue && tokenValue !== ' ') {
                        //删除当前无效token
                        uni.removeStorageSync('token');
                    }
                    //调用重新获取token方法
                    getNewToken().then((res) => {
                        //获取token成功,将当前请求存入到callback
                        config.callback = resolve;
                        //获取token成功,重新发起请求
                        req(config)
                    })
                } else if (res.statusCode === 200) {
                    //token有效,返回成功
                    resolve(res.data)
                }
            },
            fail(err) {
                console.log('request', err)
                //请求失败
                reject(err)
            }
        })
    })
}

//重新获取token
export function getNewToken() {
    return new Promise((resolve, reject) => {
       //调用uni.login获取小程序用户code 
       uni.login({
            success(res) {
                //调用login登录
                let loginRes = login({
                    code: res.code
                });
                resolve(loginRes);
            },
            fail(err) {
                reject()
                console.error('wx login fail', err);
            }
        });
    })
}

你可能感兴趣的:(开发笔记,微信小程序,小程序,安全)