成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術文章
文章詳情頁

Vue axios獲取token臨時令牌封裝案例

瀏覽:132日期:2022-11-23 15:40:00

前言

為什么非要寫這個博客呢?因為這件事讓我有一種蛋蛋的優疼。剩下的都別問,反正問我也不會說。因為流程圖我都不想(懶得)畫。

開發架構

前端頁面:Vue

網絡請求:Axios;方式:vue add axios

緩存方案

全局變量:Vuex

本地緩存:LocalStorage

技術依賴

你猜?

背景

公司開發一個嵌入App的Web頁面,安全方面使用老套路:App通過URL傳參給前端(包含簽名),前端把參數透傳給H5后端驗簽,完事兒之后前端再決定用戶是否合法。另外定義了N個JS方法前端根據固定GET參數判斷是安卓還是蘋果來調用。

初步設想

關于token設計方案的初步設想是這樣的:第一次進入的時候獲取token,后端檢查簽名是否通過。不通過則彈框請從合法途徑進入頁面并且不消失。

否則就可以讓用戶繼續后續操作,直到后端返回token過期特定狀態碼回來前端在用戶無感的情況下調用JS方法重新獲取URL參數請求token,完事兒之后繼續用戶的請求操作。(為避免用戶使用舊token在其他地方操作數據,每次獲取token都重新從App中獲取并驗證,而不是在接口中刷新并返回新的token)

蛋疼事項

一期的時候定義URL參數時沒有版本控制,導致二期新增JS方法迭代版本時前端新增頁面調用了未知方法頁面毫無反應;埋點數據也不知道是幾期的…

為盡量避免請求過程中出現token過期導致的1次請求變3次請求現象每次調用請求之前需要先檢查token時效的異步方法(如果token過期則調用getToken獲取新的token并存儲在本地)導致block嵌套。

后面又封裝了N個方法就不說了…

升級設想

版本什么的這個先不說,就這個token問題我總不能每次新增一個請求就復制粘貼復制粘貼的吧?能煩死人!那我只能在axios請求之前判斷token時效性啦。

直奔主題

函數聲明

getToken:從本地取已存儲token

checkToken:檢查token時效,失效調用refreshToken函數成功則存儲本地,否則返回錯誤原因

refreshToken:調用JS方法從App獲取簽名參數重新請求token

注意事項

在checkToken過程中token過期時,先移除本地已過期token緩存數據。

/* eslint-disable no-console *//* eslint-disable no-unused-vars */'use strict';import Vue from ’vue’;import axios from 'axios';import { getToken } from ’../utils/storage.js’import { checkToken, refreshToken, clearCache } from '../utils/utils.js';// Full config: https://github.com/axios/axios#request-config// axios.defaults.baseURL = process.env.baseURL || process.env.apiUrl || ’’;// axios.defaults.headers.common[’Authorization’] = AUTH_TOKEN;// axios.defaults.headers.post[’Content-Type’] = ’application/x-www-form-urlencoded’;axios.defaults.headers.post['Content-Type'] = 'application/json';let cancel, promiseArr = {};let config = { baseURL: process.env.VUE_APP_BASE_URL, timeout: 8 * 1000, // Timeout withCredentials: true, // Check cross-site Access-Control};const _axios = axios.create(config);_axios.interceptors.request.use( function (config) { // Do something before request is sent let token = getToken(); // alert('token1:' + token); //發起請求時,取消掉當前正在進行的相同請求 if (promiseArr[config.url]) { promiseArr[config.url]('請稍后'); promiseArr[config.url] = cancel; } else { promiseArr[config.url] = cancel; } if (token) { return checkToken(null) .then((result) => { // console.log('refreshToken result:', result); if (result === true) { token = getToken() // alert('token2:' + token); config.headers.common['authorization'] = token; return config; } else { return Promise.reject(Error(result)) } }).catch((err) => { // 終止這個請求 return Promise.reject(err); }); } return config; }, function (error) { // Do something with request error return Promise.reject(error); });// Add a response interceptor_axios.interceptors.response.use( function (response) { // Do something with response data let { status, statusText, data } = response; if (err_check(status, statusText, data) && data) { // var randomColor = `rgba(${parseInt(Math.random() * 255)},${parseInt( // Math.random() * 255 // )},${parseInt(Math.random() * 255)})`; // console.log( // '%c┍------------------------------------------------------------------┑', // `color:${randomColor};` // ); // console.log('| 請求地址:', response.config.url); // console.log('| 請求參數:', response.config.data); // console.log('| 返回數據:', response.data); // console.log( // '%c┕------------------------------------------------------------------┙', // `color:${randomColor};` // ); if (data.resCode === '0001') { clearCache() var config = response.config; var url = config.url; url = url.replace('/apis', '').replace(process.env.VUE_APP_BASE_URL, '') config.url = url; // alert(JSON.stringify(config)) return refreshToken(null) .then((result) => { // console.log('refreshToken result:', result); if (result == true) { let token = getToken() if (token) {config.headers['authorization'] = token; } return axios(config).then((result) => {let { status, statusText, data } = result;// console.log(’接口二次請求 result:’, result);if (err_check(status, statusText, data) && data) { return Promise.resolve(data)} else { return Promise.reject(Error(data.resDesc));} }).catch((err) => {// console.log(’接口二次請求 err:’ + err);return Promise.reject(err); }); } else { // alert('result:' + result) return Promise.reject(Error(data.resDesc)) } }).catch((err) => { // 終止這個請求 // alert('終止這個請求:' + err.message) // console.log('refreshToken err:', err); return Promise.reject(err); }); } else { return Promise.resolve(data); } } else { return Promise.reject(Error(statusText)); } // return response; }, function (error) { // Do something with response error // console.log('error', error); return Promise.reject(error); });// eslint-disable-next-line no-unused-varsconst err_check = (code, message, data) => { if (code == 200) { return true; } return false;};Plugin.install = function (Vue, options) { Vue.axios = _axios; window.axios = _axios; Object.defineProperties(Vue.prototype, { axios: { get() { return _axios; } }, $axios: { get() { return _axios; } }, });};Vue.use(Plugin)export default Plugin;

補充知識:vue+ axios+token 封裝axios 封裝接口url,帶token請求,token失效刷新

一、封裝axios

import axios from ’axios’import qs from 'qs' const TIME_OUT_MS = 60 * 1000 // 默認請求超時時間//axios.defaults.baseURL = ’http://localhost:8080’; // http request 攔截器axios.interceptors.request.use( config => { if ($cookies.get('access_token')) { // 判斷是否存在token,如果存在的話,則每個http header都加上token config.headers.Authorization =’Bearer ’+ $cookies.get('access_token'); } return config; }, err => { return Promise.reject(err);}); // http response 攔截器axios.interceptors.response.use( response => { return response; }, error => { console.log('response error :'+error); if (error.response) { switch (error.response.status) {case 401: console.log('token 過期'); var config = error.config; refresh(config); return; } } return Promise.reject(error) // 返回接口返回的錯誤信息 });/**刷新token*/function refresh(config){ var refreshToken = $cookies.get('refresh_token'); var grant_type = 'refresh_token'; axios({ method: ’post’, url: ’/oauth/token’, data: handleParams({'grant_type':grant_type,'refresh_token':refreshToken}), timeout: TIME_OUT_MS, headers: {} }).then( (result) => { if(result.data.access_token){ //重新保存token$cookies.set('access_token',result.data.access_token);$cookies.set('refresh_token',result.data.refresh_token);//需要重新執行axios(config); }else{ //this.$events.emit(’goto’, ’login’);window.location.reload(); } } ).catch((error) => { //this.$events.emit(’goto’,’login’); window.location.reload(); });}/** @param response 返回數據列表*/function handleResults (response) { var result = { success: false, message: ’’, status: [], errorCode: ’’, data: {} } if (response.status == ’200’) { result.status = response.status; result.data = response.data; result.success = true; } return result} // function handleUrl (url) {// //url = BASE_URL + url// url =root +url;// // BASE_URL是接口的ip前綴,比如http:10.100.1.1:8989/// return url// } /** @param data 參數列表* @return*/function handleParams (data) { return qs.stringify(data);} export default { /* * @param url * @param data * @param response 請求成功時的回調函數 * @param exception 異常的回調函數 */ post (url, data, response, exception) { axios({ method: ’post’, //url: handleUrl(url), url: url, data: handleParams(data), timeout: TIME_OUT_MS, headers: {//’Content-Type’: ’application/json; charset=UTF-8’ } }).then( (result) => {response(handleResults(result)) } ).catch( (error) => {if (exception) { exception(error)} else { console.log(error)} } ) }, /* * get 請求 * @param url * @param response 請求成功時的回調函數 * @param exception 異常的回調函數 */ get (url,data, response, exception) { axios({ method: ’get’, url: url, params:data, timeout: TIME_OUT_MS, headers: {’Content-Type’: ’application/json; charset=UTF-8’ } }).then( (result) => {response(handleResults(result)) } ).catch( (error) => {console.log('error'+response);if (exception) { exception(error)} else { console.log(error)} } ) }}

二、配置axios 跨域,以及請求baseUrl

1.config-->index.js

’’use strict’// Template version: 1.3.1// see http://vuejs-templates.github.io/webpack for documentation. const path = require(’path’) //引入跨域配置var proxyConfig = require(’./proxyConfig’) module.exports = { dev: { // Paths assetsSubDirectory: ’static’, assetsPublicPath: ’/’, //proxyTable: {}, //默認跨域配置為空 proxyTable: proxyConfig.proxy, // Various Dev Server settings host: ’localhost’, // can be overwritten by process.env.HOST port: 8886, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined autoOpenBrowser: false, errorOverlay: true, notifyOnErrors: true, poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- /** * Source Maps */ // https://webpack.js.org/configuration/devtool/#development devtool: ’cheap-module-eval-source-map’, // If you have problems debugging vue-files in devtools, // set this to false - it *may* help // https://vue-loader.vuejs.org/en/options.html#cachebusting cacheBusting: true, cssSourceMap: true }, build: { // Template for index.html index: path.resolve(__dirname, ’../dist/index.html’), // Paths assetsRoot: path.resolve(__dirname, ’../dist’), assetsSubDirectory: ’static’, // 項目名字改變時這里需要變化 原先為assetsPublicPath: ’.’ assetsPublicPath: ’./’, /** * Source Maps */ productionSourceMap: true, // https://webpack.js.org/configuration/devtool/#production devtool: ’#source-map’, // Gzip off by default as many popular static hosts such as // Surge or Netlify already gzip all static assets for you. // Before setting to `true`, make sure to: // npm install --save-dev compression-webpack-plugin productionGzip: false, productionGzipExtensions: [’js’, ’css’], // Run the build command with an extra argument to // View the bundle analyzer report after build finishes: // `npm run build --report` // Set to `true` or `false` to always turn it on or off bundleAnalyzerReport: process.env.npm_config_report }}

2.config目錄下創建一個文件 proxyConfig.js文件

module.exports={ proxy:{ ’/’:{ //將localhost:8081 映射為 /apis target:’http://localhost:8080’,//接口地址 changeOrigin: true,// 如果接口跨域,需要進行這個參數配置 secure:false, //如果接口是HTTPS接口,需要設置成true pathRewrite:{’^/’:’’ } } }}

三、封裝API 請求Url port.js

export default { oauth: { login: ’/oauth/token’, // 登錄 logout: ’/oauth/logout’ // // 退出 }, user: { addUser: ’/user/add’, updateUser: ’/user/update’, getUser:’/user/’, //+ Id exists:’/exists/’, // +id enable:’/enable/’, // +id disable:’/disable/’, // +id delete:’/delete/’, //+id password:’/password ’, query:’/query’ }}

四、main.js 引入

import http from ’./plugins/http.js’import ports from ’./plugins/ports’Vue.prototype.http = httpVue.prototype.ports = ports

五、使用

login.vue中使用

login() { this.http.post(this.ports.oauth.login,{username:this.userId, password:this.password,grant_type:’password’}, res => { if (res.success) { // 返回正確的處理 頁面跳轉 this.$events.emit(’goto’, ’edit’); } else { // 返回錯誤的處理 //alert('等待處理'); }},err =>{ //console.log('正在處理'+err.response.status); if(err.response.status==’400’){ //顯示用戶名或密碼錯誤 this.$refs.username.focus(); this.$refs.hint.click(); } }) }

以上這篇Vue axios獲取token臨時令牌封裝案例就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持好吧啦網。

標簽: IOS
相關文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
不卡的av中国片| 亚洲精品免费播放| 亚洲乱码一区二区三区在线观看| 97超碰欧美中文字幕| 欧美电影免费观看高清完整版在 | 亚洲电影在线| 国产精品乱码人人做人人爱| 91老司机福利 在线| 久久色.com| 91蜜桃免费观看视频| 国产亚洲一本大道中文在线| 99久久精品费精品国产一区二区| 日韩欧美电影一区| 大白屁股一区二区视频| 51精品国自产在线| 国产高清精品网站| 精品国产第一区二区三区观看体验| 国产v日产∨综合v精品视频| 日韩一级片在线观看| 高清成人免费视频| 亚洲永久免费| 天堂影院一区二区| 在线免费视频一区二区| 激情丁香综合五月| 欧美一级在线观看| 不卡欧美aaaaa| 欧美国产日本视频| 尤物网精品视频| 一区二区视频免费在线观看| 国产精品视频| 免费成人美女在线观看.| 欧美日本一区二区在线观看| 国产成人精品aa毛片| 精品精品欲导航| 91麻豆国产福利在线观看| 亚洲国产精品激情在线观看| 亚洲手机视频| 亚洲午夜久久久久久久久电影院 | 欧洲一区二区三区在线| 久久精品国产精品亚洲精品 | 日韩精品一区二区在线| 91亚洲国产成人精品一区二区三| 国产日韩欧美制服另类| 在线欧美日韩| 亚洲一二三级电影| 在线观看免费亚洲| 国产精品1024| 国产女主播一区| 一本色道久久精品| 日本美女一区二区三区| 91精品国产入口在线| 97se亚洲国产综合自在线不卡| 中文字幕亚洲成人| 久久精品一区| 国产美女av一区二区三区| 精品国产一区二区三区av性色| 91网上在线视频| 亚洲欧美日韩系列| 色婷婷久久久综合中文字幕| 国产一区二区三区精品视频| 国产亚洲精久久久久久| 日韩天堂av| 国产伦一区二区三区色一情| 亚洲h动漫在线| 91精品国产综合久久国产大片| 91麻豆文化传媒在线观看| 亚洲人快播电影网| 色婷婷精品久久二区二区蜜臂av | 亚洲国产乱码最新视频| 欧美色图在线观看| 91丝袜美腿高跟国产极品老师 | 美女脱光内衣内裤视频久久网站| 精品av综合导航| 亚洲日产国产精品| 免费精品视频在线| 26uuu国产电影一区二区| 一本久道综合久久精品| 国产精品一区二区久久不卡| 国产精品情趣视频| 欧美性一区二区| 欧美日本高清| 蜜臀久久99精品久久久久宅男| 日韩精品在线网站| 99亚洲视频| 国产91对白在线观看九色| 亚洲黄色av一区| 欧美一区二区三区爱爱| 99精品国产99久久久久久福利| 国产在线精品国自产拍免费| 18涩涩午夜精品.www| 欧美欧美欧美欧美| 亚洲三级免费| 岛国精品在线播放| 亚洲大片一区二区三区| 欧美成人video| 欧美中日韩免费视频| 99精品黄色片免费大全| 五月激情综合婷婷| 久久精品一二三| 91搞黄在线观看| 欧美连裤袜在线视频| 欧美aaa在线| 中文字幕一区二区三| 欧美一区二区视频在线观看| 国产精品夜夜夜| 91小视频在线免费看| 激情综合五月天| 中文字幕乱码亚洲精品一区| 欧美女孩性生活视频| 一本不卡影院| 91丨九色丨蝌蚪丨老版| 老司机精品视频在线| 日韩一区在线看| 日韩你懂的在线观看| 色噜噜狠狠色综合中国| 亚洲国产高清一区二区三区| 成人免费视频免费观看| 日韩和欧美一区二区三区| 亚洲国产成人一区二区三区| 欧美一区二区视频观看视频| 久久综合五月| 亚洲福利国产| 91亚洲大成网污www| 国产麻豆午夜三级精品| 天天综合天天综合色| 亚洲色图欧美偷拍| 久久久精品蜜桃| 欧美一区二区三区视频免费播放| 久久久久久久高潮| 亚洲精品看片| 欧美精品一区二区视频| 国产91精品露脸国语对白| 免费在线一区观看| 亚洲一卡二卡三卡四卡 | 国产电影一区二区三区| 石原莉奈在线亚洲三区| 亚洲视频在线一区| 国产欧美一区二区精品性色超碰| 日韩精品专区在线| 欧美狂野另类xxxxoooo| 91久久一区二区| 亚洲一区日本| 亚洲激情网址| 国产综合激情| 9色porny自拍视频一区二区| 国产福利一区在线| 精品一区二区免费看| 青青草97国产精品免费观看无弹窗版| 亚洲影视在线观看| 亚洲色图都市小说| 日本一区二区视频在线| 精品日韩99亚洲| 欧美一级精品在线| 欧美一区二区三区视频在线观看 | 99国内精品| 亚洲五月婷婷| 欧美黄色aaaa| 激情综合色综合久久| 麻豆精品一二三| 蜜臀av在线播放一区二区三区 | 国产精品国产三级国产a | 综合av第一页| 中文字幕一区二| 综合久久一区二区三区| 国产精品久久午夜| 国产精品毛片久久久久久久| 国产欧美一区二区精品忘忧草| 久久综合久久99| 久久亚洲欧美国产精品乐播| 欧美精品一区在线观看| 久久久亚洲精品一区二区三区| 久久蜜桃av一区精品变态类天堂| 亚洲精品在线观看网站| 久久综合久久综合久久综合| 欧美精品一区二区三区一线天视频| 精品国产一区二区三区av性色| 精品久久久久一区二区国产| www亚洲一区| 国产校园另类小说区| 国产日韩高清在线| 中文av字幕一区| 亚洲欧美成人一区二区三区| 亚洲综合一二区| 日精品一区二区三区| 麻豆精品视频在线观看视频| 国产一区二区三区四| 丁香婷婷综合色啪| 欧美一区影院| 91久久国产综合久久蜜月精品| 中文亚洲字幕| 久久天堂精品| 欧洲一区在线电影| 91精品在线观看入口| 欧美刺激脚交jootjob| 26uuu色噜噜精品一区| 国产欧美一区在线| 亚洲天堂免费看| 亚洲成av人综合在线观看| 麻豆精品新av中文字幕| 国产一区二区按摩在线观看|