小程序token失效问题

请求时token过期自动刷新token

  1. 在开发过程中,我们都会接触到token,token的作用是什么呢?了解一下Token 认证的来龙去脉主要的作用就是为了安全,用户登陆时,服务器会随机生成一个有时效性的token,用户的每一次请求都需要携带上token,证明其请求的合法性,服务器会验证token,只有通过验证才会返回请求结果。

  2. 当token失效时,现在的网站一般会做两种处理,一种是跳转到登陆页面让用户重新登陆获取新的token,另外一种就是当检测到请求失效时,网站自动去请求新的token,第二种方式在app保持登陆状态上面用得比较多。

  3. 下面进入主题,我们请求用的是axios,不管用何种请求方式,刷新token的原理都是一样的。

封装了一个统一的请求函数

import Vue from 'vue'
import {
	keepLogin
} from './publicFunction.js';
import api from './interface.js';
import {
	mapActions
} from 'vuex';
const commonUrl = "https://www.qixinlive.com:1443/"; //线上地址
// const commonUrl = "http://192.168.2.14:8010/"; //本地地址
// const commonUrl = "https://t.qixinlive.com:1441/"; //测试地址

const vue = new Vue()
let isRefreshing = true;
// post请求封装
function postRequest(url, data, type) {
	if (type == '1') {
		vue.$store.dispatch('loadingShowTrue')
	}
	var promise = new Promise((resolve, reject) => {
		var that = this;
		let newUrl = ''
		if (commonUrl === 'http://192.168.2.14:8010/') {
			let arr = url.split('/')
			newUrl = arr[0].substring(0, arr[0].length - 3) + '/' + arr[1]
		} else {
			newUrl = url
		}

		uni.request({
			url: commonUrl + newUrl,
			data: data,
			method: "POST",
			header: {
				"content-type": "application/json",
				token: uni.getStorageSync("token"),
			},
			success: (res) => {
				// 此判断可根据自己需要更改
				if (type == 'recognization') {
					resolve(res)

				} else if (type === 'confirm') {
					// reject(res);
					resolve(res)
				} else {
					if (type === 'confirm') {
						if (res.data.status !== 'success') {
							reject(res);
						}
					} else if (res.data.status !== 'success') {
						return uni.showToast({
							title: res.data.msg,
							icon: 'none'
						})
					}
					resolve(res)
				}
			},
			fail: (err) => {
				uni.showToast({
					title: '请求接口失败!',
					icon: 'error'
				})
				reject(err)
			},
			complete(res) {
				if (type == '1') {
					vue.$store.dispatch('loadingShowFalse')
					if (res.statusCode == 413) {
						uni.showToast({
							title: '上传文件过大',
							icon: 'error'
						})
					}
				}
				if (res.statusCode == 401) {
					if (isRefreshing) {
						refreshTokenRequst()
					}
					isRefreshing = false;
					const retryOriginalRequest = new Promise((resolve) => {
						addSubscriber(() => {
							resolve(postRequest(url, data))
						})
					});
					return retryOriginalRequest;
				} else {
					return res;
				}
			}
			//隐藏loading
		})
	});
	return promise

}


let subscribers = [];

function refreshTokenRequst() {
	keepLogin(api.userApi, uni.getStorageSync('userId'))
	setTimeout(() => {
		onAccessTokenFetched()
	}, 1000)
	isRefreshing = true;
}

function onAccessTokenFetched() {
	subscribers.forEach(callback => {
		callback()
	})
	subscribers = [];
}

function addSubscriber(callback) {
	subscribers.push(callback)
}

// get请求封装
function getRequest(url, data) {
	uni.showLoading({
		title: '加载中'
	})
	var promise = new Promise((resolve, reject) => {
		var that = this;
		var postData = data;
		uni.request({
			url: commonUrl + url,
			data: postData,
			method: "GET",
			dataType: "json",
			header: {
				"content-type": "application/json"
			},
			success: (res) => {
				// 此判断可根据自己需要更改
				if (res.data.status !== 'success') {
					return uni.showToast({
						title: '获取数据失败!'
					})
				}
				resolve(res)
			},
			fail: (err) => {
				uni.showToast({
					title: '请求接口失败!'
				})
				reject(err)
			},
			complete(res) {
				// 隐藏loading
				uni.hideLoading()

			}
		});
	});
	return promise;
}

export default {
	post: postRequest,
	get: getRequest,
};

总结:其实token失效,自动刷新token,在页面只有一个请求的时候是比较好处理的,但是如果页面同时有多个请求,并且都会产生token失效,这就需要一些稍微复杂的处理,解决方式主要是用了Promise 函数来进行处理。每一个token失效的请求都会存到一个Promise函数集合里面,当刷新token的函数执行完毕后,才会批量执行这些Promise函数,返回请求结果。还有一点要注意一下,这儿设置一个刷新token的开关isRefreshing,这个是非常有必要的,防止重复请求。

获取token

export function keepLogin(api, userId) {
	if (userId) {
		uni.request({
			url: `${api}driverRememberAutoLogin`,
			data: {
				userId: userId,
				// loginType: 11,
			},
			method: 'POST',
			success(reskeepLogin) {
				if (reskeepLogin.data.status === 'success') {
					if (reskeepLogin.data.driverTenantId) {
					    uni.setStorageSync('driverTenantId',reskeepLogin.data.driverTenantId)
					}
					uni.setStorageSync('userId',reskeepLogin.data.userId)
					uni.setStorageSync('token',reskeepLogin.data.accessToken)
					uni.setStorageSync('avatar',reskeepLogin.data.avatar)
					uni.setStorageSync('username',reskeepLogin.data.username)
					uni.setStorageSync('phone',reskeepLogin.data.secretMobilePhoneNumber)
				}
			},
			fail() {
				uni.showToast({
					title: '网络异常,稍后再试',
					icon: "none"
				})
			}
		})
	}
}
import Vue from 'vue'
const api = {

	//本地用接口
	driverWaybillApi: 'http://192.168.2.14:8010/driverWaybill/',
	orderCarrierApi: 'http://192.168.2.14:8010/ordercarrier/',
	driverAppCenterApi: 'http://192.168.2.14:8010/driverAppCenter/',
	driverpactApi: 'http://192.168.2.14:8010/driverpact/',
	receiptcarrierApi: 'http://192.168.2.14:8010/receiptcarrier/',
	userApi: 'http://192.168.2.14:8010/account/',
	carrierApi: 'http://192.168.2.14:8010/carrier/',
	userMobileApi: 'http://192.168.2.14:8010/msg/',
	//新增
	tenantApi: 'http://192.168.2.14:8010/tenant/',
	trackcarrierApi: 'http://192.168.2.14:8010/trackcarrier/',
	websocketApi: "ws://192.168.2.65:7200/",
	erCodeApi: 'http://192.168.2.14:8010/api/'
}

export default api
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值