uni-app 无痛刷新 token 方法
<p>为了给用户一个流畅的体验, token 过期后需要重新请求新的 token 替换过期的 token </p><p>前端在请求接口时,和后端定义好了,如果状态码为 401 ,则表明 token 过期,需要前端请求新的 token</p>
<p> 流程思路参考: https://www.jianshu.com/p/58f05bf13b7d</p>
<p>大概流程如下:</p>
<p>1.用户登录之后,后端会返回两个 token ,分别为 accessToken 和 refreshToken 存储到 Storage</p>
<p>平时请求数据时,请求头使用 accessToken 来发送接口</p>
<p>2.当返回401 token 过期后, 我们通过接口向后端获取新的 token ,请求参数为 refreshToken</p>
<p>3.我们拿到新的 accessToken 和 refreshToken 之后, 替换掉之前的 Storage 中存储的 token</p>
<p>4.同时还要将我们报 401 的哪个接口 ,使用新的 accessToken ,重新请求一次, 拿到数据,实现无痛刷新 token</p>
<p>5.如果后端返回的新的 token 也无法使用,表明需要重新登录,跳到登录页(<span style="color: rgba(255, 0, 0, 1)">这一步可以灵活使用,我个人用的是一个路由插件配合使用的</span>: https://ext.dcloud.net.cn/plugin?id=578)</p>
<p> </p>
<p><span style="font-size: 14pt"><strong>配合uni-app的插件进行使用和实现:</strong></span></p>
<p><span style="font-size: 14pt"><span style="font-size: 16px">到uni-app的插件市场下载 </span></span><strong>封装的request网络请求 </strong><span style="font-size: 14pt"><span style="font-size: 16px">,按照文档配置到自己的项目上</span></span></p>
<p><span style="font-size: 14pt"><span style="font-size: 16px">地址: https://ext.dcloud.net.cn/plugin?id=159</span></span></p>
<p><span style="font-size: 14pt"><span style="font-size: 16px">配置好后修改 vmeitime-http 文件夹下的 index.js 文件</span></span></p>
<p> </p>
<p><img src="https://img2018.cnblogs.com/blog/1623487/201910/1623487-20191031155609814-113830902.png"></p>
<p> </p>
<p> <img src="https://img2018.cnblogs.com/blog/1623487/201910/1623487-20191031160033765-657856026.png"></p>
<p><span style="color: rgba(255, 0, 0, 1); font-size: 18px"> 再修改 vmeitime-http 文件夹下的 interface.js 文件,将401状态暴漏出来</span></p>
<p> <img src="https://img2018.cnblogs.com/blog/1623487/201910/1623487-20191031160301782-1530549040.png"></p>
<p><span style="color: rgba(255, 0, 0, 1)"><strong><span style="font-size: 16px">如果看到这里还是看不明白,那么请看我的源码,请注意我使用了两个插件,观众们酌情理解,仔细消化,配合到自己的项目中思考...</span></strong></span></p>
<p><span style="color: rgba(255, 0, 0, 1)"><strong><span style="font-size: 16px">源码点下面的折叠小加号 ⬇ (老有人问我要源码,源码在下面)</span></strong></span></p>
<p> </p>
<div class="cnblogs_code"><img id="code_img_closed_56aa5772-43d5-4d42-8adb-ef7e18f36433" class="code_img_closed lazyload" data-src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif"><img id="code_img_opened_56aa5772-43d5-4d42-8adb-ef7e18f36433" class="code_img_opened lazyload" style="display: none" data-src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif">
<div id="cnblogs_code_open_56aa5772-43d5-4d42-8adb-ef7e18f36433" class="cnblogs_code_hide">
<pre>import http from './interface'<span style="color: rgba(0, 0, 0, 1)">
import config from </span>'./config'
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> request.js</span>
import Vue from 'vue'<span style="color: rgba(0, 0, 0, 1)">
import Routerfrom </span>'@/router'
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">...其它逻辑代码</span>
<span style="color: rgba(0, 0, 0, 1)">
export const execute </span>= (name, data = {}) =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置请求前拦截器</span>
http.interceptor.request = (config) =><span style="color: rgba(0, 0, 0, 1)"> {
let token </span>= uni.getStorageSync('accessToken'<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">delete</span> config.header['x-access-token'<span style="color: rgba(0, 0, 0, 1)">]
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (token) {
config.header[</span>'x-access-token'] =<span style="color: rgba(0, 0, 0, 1)"> token
}
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置请求结束后拦截器</span>
http.interceptor.response = async (response) =><span style="color: rgba(0, 0, 0, 1)"> {
const statusCode </span>=<span style="color: rgba(0, 0, 0, 1)"> response.statusCode;
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (statusCode === 401<span style="color: rgba(0, 0, 0, 1)">) {
response </span>=<span style="color: rgba(0, 0, 0, 1)"> await doRequest(response)
}
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (statusCode === 402<span style="color: rgba(0, 0, 0, 1)">) {
uni.removeStorageSync(</span>'accessToken'<span style="color: rgba(0, 0, 0, 1)">);
uni.removeStorageSync(</span>'refreshToken'<span style="color: rgba(0, 0, 0, 1)">);
uni.removeStorageSync(</span>'realname'<span style="color: rgba(0, 0, 0, 1)">);
let jump </span>= uni.getStorageSync('jump'<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">jump) {
setTimeout(() </span>=><span style="color: rgba(0, 0, 0, 1)"> {
uni.showModal({
title: </span>'提示'<span style="color: rgba(0, 0, 0, 1)">,
content: </span>'您的账号在其它地点登录!'<span style="color: rgba(0, 0, 0, 1)">,
showCancel: </span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">,
success: </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(res) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (res.confirm) {
Router.push({
name: </span>'login'<span style="color: rgba(0, 0, 0, 1)">,
params: {
</span>'RouterName': 'home'<span style="color: rgba(0, 0, 0, 1)">
}
})
}
},
})
});
uni.setStorageSync(</span>'jump', 'true'<span style="color: rgba(0, 0, 0, 1)">)
}
}
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (statusCode == 403<span style="color: rgba(0, 0, 0, 1)">) {
let jump </span>= uni.getStorageSync('jump'<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">jump) {
setTimeout(() </span>=><span style="color: rgba(0, 0, 0, 1)"> {
Router.replace({
name: </span>'login'<span style="color: rgba(0, 0, 0, 1)">,
params: {
</span>'RouterName': 'home'<span style="color: rgba(0, 0, 0, 1)">
}
})
},</span>500<span style="color: rgba(0, 0, 0, 1)">)
uni.setStorageSync(</span>'jump', 'true'<span style="color: rgba(0, 0, 0, 1)">)
}
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 统一处理错误请求</span>
const code =<span style="color: rgba(0, 0, 0, 1)"> response.data.code;
const message </span>=<span style="color: rgba(0, 0, 0, 1)"> response.data.message;
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (response.statusCode == 200 && code !== 0 && code != -1 &&<span style="color: rgba(0, 0, 0, 1)"> code) {
uni.showToast({
title: message,
icon: </span>"none"<span style="color: rgba(0, 0, 0, 1)">,
duration: </span>2000<span style="color: rgba(0, 0, 0, 1)">
});
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> response;
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> http.request({
name: name,
baseUrl: config.base,
url: config.interface.path,
method: config.interface.method </span>? config.interface.method : 'GET'<span style="color: rgba(0, 0, 0, 1)">,
dataType: </span>'json'<span style="color: rgba(0, 0, 0, 1)">,
data,
})
}
export </span><span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)"> {
execute
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 刷新 token 方法</span>
async <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> doRequest(response) {
const res </span>= await execute('refresh', {refreshToken: uni.getStorageSync('refreshToken'<span style="color: rgba(0, 0, 0, 1)">)})
const {
code,
data
} </span>=<span style="color: rgba(0, 0, 0, 1)"> res.data
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (code == 0<span style="color: rgba(0, 0, 0, 1)">) {
uni.setStorageSync(</span>'accessToken'<span style="color: rgba(0, 0, 0, 1)">, data.accessToken)
uni.setStorageSync(</span>'refreshToken'<span style="color: rgba(0, 0, 0, 1)">, data.refreshToken)
let config </span>=<span style="color: rgba(0, 0, 0, 1)"> response.config
config.header[</span>'x-access-token'] =<span style="color: rgba(0, 0, 0, 1)"> data.accessToken
const resold </span>=<span style="color: rgba(0, 0, 0, 1)"> await execute(config.name,{ ...config.data
})
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> resold
} </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
uni.removeStorageSync(</span>'accessToken'<span style="color: rgba(0, 0, 0, 1)">);
uni.removeStorageSync(</span>'refreshToken'<span style="color: rgba(0, 0, 0, 1)">);
uni.showToast({
title: </span>'登陆过期请重新登陆!'<span style="color: rgba(0, 0, 0, 1)">,
icon: </span>"none"<span style="color: rgba(0, 0, 0, 1)">,
success() {
Router.push({
name: </span>'login'<span style="color: rgba(0, 0, 0, 1)">,
params: {
</span>'RouterName': 'home'<span style="color: rgba(0, 0, 0, 1)">
}
})
}
});
}
}</span></pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p> </p>
</div>
<div id="MySignature" role="contentinfo">
如果我的文章对您有帮助,欢迎您点击推荐以及评论 QAQ<br><br>
来源:https://www.cnblogs.com/jun-qi/p/11771771.html
頁:
[1]