用户飞天 發表於 2019-10-31 16:03:00

uni-app 无痛刷新 token 方法

<p>为了给用户一个流畅的体验, token 过期后需要重新请求新的 token 替换过期的 token&nbsp;</p>
<p>前端在请求接口时,和后端定义好了,如果状态码为 401 ,则表明 token 过期,需要前端请求新的 token</p>
<p>&nbsp;流程思路参考:&nbsp;https://www.jianshu.com/p/58f05bf13b7d</p>
<p>大概流程如下:</p>
<p>1.用户登录之后,后端会返回两个 token ,分别为&nbsp;accessToken 和&nbsp;refreshToken 存储到&nbsp;Storage</p>
<p>平时请求数据时,请求头使用&nbsp;accessToken 来发送接口</p>
<p>2.当返回401 token 过期后, 我们通过接口向后端获取新的 token ,请求参数为&nbsp;refreshToken</p>
<p>3.我们拿到新的&nbsp;accessToken 和&nbsp;refreshToken 之后, 替换掉之前的&nbsp;Storage 中存储的 token</p>
<p>4.同时还要将我们报 401 的哪个接口 ,使用新的&nbsp;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>&nbsp;</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的插件市场下载&nbsp;</span></span><strong>封装的request网络请求&nbsp;</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">地址:&nbsp;https://ext.dcloud.net.cn/plugin?id=159</span></span></p>
<p><span style="font-size: 14pt"><span style="font-size: 16px">配置好后修改&nbsp;vmeitime-http 文件夹下的&nbsp; index.js 文件</span></span></p>
<p>&nbsp;</p>
<p><img src="https://img2018.cnblogs.com/blog/1623487/201910/1623487-20191031155609814-113830902.png"></p>
<p>&nbsp;</p>
<p>&nbsp;<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">&nbsp;再修改&nbsp;vmeitime-http 文件夹下的&nbsp; interface.js 文件,将401状态暴漏出来</span></p>
<p>&nbsp;<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>&nbsp;</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 = {}) =&gt;<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) =&gt;<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) =&gt;<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>=&gt;<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>=&gt;<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 &amp;&amp; code !== 0 &amp;&amp; code != -1 &amp;&amp;<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>&nbsp;</p>

</div>
<div id="MySignature" role="contentinfo">
    如果我的文章对您有帮助,欢迎您点击推荐以及评论 QAQ<br><br>
来源:https://www.cnblogs.com/jun-qi/p/11771771.html
頁: [1]
查看完整版本: uni-app 无痛刷新 token 方法