Vue+axios實現登陸攔截,axios封裝(報錯,鑑權,跳轉,攔截,提示)
axios封裝
需求及實現
- 統一捕獲介面報錯
- 彈窗提示
- 報錯重定向
- 基礎鑑權
- 表單序列化
實現的功能
- 統一捕獲介面報錯 : 用的axios內建的攔截器
- 彈窗提示: 引入
Element UI
的Message
元件 - 報錯重定向: 路由鉤子
- 基礎鑑權: 服務端過期時間戳和token,還有藉助路由的鉤子
- 表單序列化: 我這邊直接用
qs
(npm模組),你有時間也可以自己寫
用法及封裝
- 用法
// 服務層 , import預設會找該目錄下index.js的檔案,這個可能有小夥伴不知道
// 可以去了解npm的引入和es6引入的理論概念
import axiosPlugin from "./server" ;
Vue.use(axiosPlugin);
- 1
- 2
- 3
- 4
- 5
- 對axios的封裝(AXIOS:
index.js
)
import axios from "axios";
import qs from "qs";
import { Message } from "element-ui";
import router from "../router";
const Axios = axios.create({
baseURL: "/", // 因為我本地做了反向代理
timeout: 10000,
responseType: "json",
withCredentials: true, // 是否允許帶cookie這些
headers: {
"Content-Type": "application/x-www-form-urlencoded;charset=utf-8"
}
});
//POST傳參序列化(新增請求攔截器)
Axios.interceptors.request.use(
config => {
// 在傳送請求之前做某件事
if (
config.method === "post" ||
config.method === "put" ||
config.method === "delete"
) {
// 序列化
config.data = qs.stringify(config.data);
}
// 若是有做鑑權token , 就給頭部帶上token
if (localStorage.token) {
config.headers.Authorization = localStorage.token;
}
return config;
},
error => {
Message({
// 餓了麼的訊息彈窗元件,類似toast
showClose: true,
message: error,
type: "error.data.error.message"
});
return Promise.reject(error.data.error.message);
}
);
//返回狀態判斷(新增響應攔截器)
Axios.interceptors.response.use(
res => {
//對響應資料做些事
if (res.data && !res.data.success) {
Message({
// 餓了麼的訊息彈窗元件,類似toast
showClose: true,
message: res.data.error.message.message
? res.data.error.message.message
: res.data.error.message,
type: "error"
});
return Promise.reject(res.data.error.message);
}
return res;
},
error => {
// 使用者登入的時候會拿到一個基礎資訊,比如使用者名稱,token,過期時間戳
// 直接丟localStorage或者sessionStorage
if (!window.localStorage.getItem("loginUserBaseInfo")) {
// 若是介面訪問的時候沒有發現有鑑權的基礎資訊,直接返回登入頁
router.push({
path: "/login"
});
} else {
// 若是有基礎資訊的情況下,判斷時間戳和當前的時間,若是當前的時間大於伺服器過期的時間
// 乖乖的返回去登入頁重新登入
let lifeTime =
JSON.parse(window.localStorage.getItem("loginUserBaseInfo")).lifeTime *
1000;
let nowTime = new Date().getTime(); // 當前時間的時間戳
console.log(nowTime, lifeTime);
console.log(nowTime > lifeTime);
if (nowTime > lifeTime) {
Message({
showClose: true,
message: "登入狀態資訊過期,請重新登入",
type: "error"
});
router.push({
path: "/login"
});
} else {
// 下面是介面回撥的satus ,因為我做了一些錯誤頁面,所以都會指向對應的報錯頁面
if (error.response.status === 403) {
router.push({
path: "/error/403"
});
}
if (error.response.status === 500) {
router.push({
path: "/error/500"
});
}
if (error.response.status === 502) {
router.push({
path: "/error/502"
});
}
if (error.response.status === 404) {
router.push({
path: "/error/404"
});
}
}
}
// 返回 response 裡的錯誤資訊
let errorInfo = error.data.error ? error.data.error.message : error.data;
return Promise.reject(errorInfo);
}
);
// 對axios的例項重新封裝成一個plugin ,方便 Vue.use(xxxx)
export default {
install: function(Vue, Option) {
Object.defineProperty(Vue.prototype, "$http", { value: Axios });
}
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 路由鉤子的調整(Router:
index.js
)
import Vue from "vue";
import Router from "vue-router";
import layout from "@/components/layout/layout";
// 版塊有點多,版塊獨立路由管理,裡面都是懶載入引入
import customerManage from "./customerManage"; // 客戶管理
import account from "./account"; //登入
import adManage from "./adManage"; // 廣告管理
import dataStat from "./dataStat"; // 資料統計
import logger from "./logger"; // 日誌
import manager from "./manager"; // 管理者
import putonManage from "./putonManage"; // 投放管理
import error from "./error"; // 服務端錯誤
import { Message } from "element-ui";
Vue.use(Router);
// 請跳過這一段,看下面的
const router = new Router({
hashbang: false,
mode: "history",
routes: [
{
path: "/",
redirect: "/adver",
component: layout,
children: [
...customerManage,
...adManage,
...dataStat,
...putonManage,
...manager,
...logger
]
},
...account,
...error
]
});
// 路由攔截
// 差點忘了說明,不是所有版塊都需要鑑權的
// 所以需要鑑權,我都會在路由meta新增新增一個欄位requireLogin,設定為true的時候
// 這貨就必須走鑑權,像登入頁這些不要,是可以直接訪問的!!!
router.beforeEach((to, from, next) => {
if (to.matched.some(res => res.meta.requireLogin)) {
// 判斷是否需要登入許可權
if (window.localStorage.getItem("loginUserBaseInfo")) {
// 判斷是否登入
let lifeTime =
JSON.parse(window.localStorage.getItem("loginUserBaseInfo")).lifeTime *
1000;
let nowTime = (new Date()).getTime(); // 當前時間的時間戳
if (nowTime < lifeTime) {
next();
} else {
Message({
showClose: true,
message: "登入狀態資訊過期,請重新登入",
type: "error"
});
next({
path: "/login"
});
}
} else {
// 沒登入則跳轉到登入介面
next({
path: "/login"
});
}
} else {
next();
}
});
export default router;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
axios可配置的一些選項,其他的具體看官網說明哈
export default {
// 請求地址
url: "/user",
// 請求型別
method: "get",
// 請根路徑
baseURL: "http://www.mt.com/api",
// 請求前的資料處理
transformRequest: [function(data) {}],
// 請求後的資料處理
transformResponse: [function(data) {}],
// 自定義的請求頭
headers: { "x-Requested-With": "XMLHttpRequest" },
// URL查詢物件
params: { id: 12 },
// 查詢物件序列化函式
paramsSerializer: function(params) {},
// request body
data: { key: "aa" },
// 超時設定s
timeout: 1000,
// 跨域是否帶Token
withCredentials: false,
// 自定義請求處理
adapter: function(resolve, reject, config) {},
// 身份驗證資訊
auth: { uname: "", pwd: "12" },
// 響應的資料格式 json / blob /document /arraybuffer / text / stream
responseType: "json",
// xsrf 設定
xsrfCookieName: "XSRF-TOKEN",
xsrfHeaderName: "X-XSRF-TOKEN",
// 下傳和下載進度回撥
onUploadProgress: function(progressEvent) {
Math.round(progressEvent.loaded * 100 / progressEvent.total);
},
onDownloadProgress: function(progressEvent) {},
// 最多轉發數,用於node.js
maxRedirects: 5,
// 最大響應資料大小
maxContentLength: 2000,
// 自定義錯誤狀態碼範圍
validateStatus: function(status) {
return status >= 200 && status < 300;
},
// 用於node.js
httpAgent: new http.Agent({ keepAlive: true }),
httpsAgent: new https.Agent({ keepAlive: true }),
// 用於設定跨域請求代理
proxy: {
host: "127.0.0.1",
port: 8080,
auth: {
username: "aa",
password: "2123"
}
},
// 用於取消請求
cancelToken: new CancelToken(function(cancel) {})
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
Vue+axios實現登陸攔截
一個專案學會vue全家桶+axios實現登入、攔截、登出功能,以及利用axios的http攔截器攔截請求和響應。
前言
該專案是利用了Github 提供的personal token作為登入token,通過token訪問你的Repository List。通過這個專案學習如何實現一個前端專案中所需要的
登入及攔截、登出、token失效的攔截及對應 axios 攔截器的使用。
準備
你需要先生成自己的 Github Personal Token(生成Token)。
Token 生成後 訪問 Demo,即可檢視你的Repository List。
專案結構
.
├── README.md
├── dist // 打包構建後的資料夾
│ ├── build.js
│ └── build.js.map
├── index.html
├── package.json
├── src
│ ├── App.vue
│ ├── assets
│ │ ├── css.css
│ │ ├── icon.css
│ │ └── logo.png
│ ├── constant
│ │ └── api.js // 配置api介面檔案
│ ├── http.js // 封裝fetch、post請求及http 攔截器配置檔案
│ ├── index.vue
│ ├── login.vue
│ ├── main.js
│ ├── repository.vue
│ ├── router.js // 路由配置檔案
│ └── store
│ ├── store.js
│ └── types.js // vuex types
└── webpack.config.js
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
技術棧
- Vue 2.0
- vue-router
- vuex
- axios
- vue-material
登入攔截邏輯
第一步:路由攔截
首先在定義路由的時候就需要多新增一個自定義欄位requireAuth
,用於判斷該路由的訪問是否需要登入。如果使用者已經登入,則順利進入路由,
否則就進入登入頁面。
const routes = [
{
path: '/',
name: '/',
component: Index
},
{
path: '/repository',
name: 'repository',
meta: {
requireAuth: true, // 新增該欄位,表示進入這個路由是需要登入的
},
component: Repository
},
{
path: '/login',
name: 'login',
component: Login
}
];
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
定義完路由後,我們主要是利用vue-router
提供的鉤子函式beforeEach()
對路由進行判斷。
router.beforeEach((to, from, next) => {
if (to.meta.requireAuth) { // 判斷該路由是否需要登入許可權
if (store.state.token) { // 通過vuex state獲取當前的token是否存在
next();
}
else {
next({
path: '/login',
query: {redirect: to.fullPath} // 將跳轉的路由path作為引數,登入成功後跳轉到該路由
})
}
}
else {
next();
}
})
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
每個鉤子方法接收三個引數:
* to: Route: 即將要進入的目標 路由物件
* from: Route: 當前導航正要離開的路由
* next: Function: 一定要呼叫該方法來 resolve 這個鉤子。執行效果依賴 next 方法的呼叫引數。
* next(): 進行管道中的下一個鉤子。如果全部鉤子執行完了,則導航的狀態就是 confirmed (確認的)。
* next(false): 中斷當前的導航。如果瀏覽器的 URL 改變了(可能是使用者手動或者瀏覽器後退按鈕),那麼 URL 地址會重置到 from 路由對應的地址。
* next(‘/’) 或者 next({ path: ‘/’ }): 跳轉到一個不同的地址。當前的導航被中斷,然後進行一個新的導航。
確保要呼叫 next 方法,否則鉤子就不會被 resolved。
完整的方法見
/src/router.js
其中,to.meta
中是我們自定義的資料,其中就包括我們剛剛定義的requireAuth
欄位。通過這個欄位來判斷該路由是否需要登入許可權。需要的話,同時當前應用不存在token,則跳轉到登入頁面,進行登入。登入成功後跳轉到目標路由。
登入攔截到這裡就結束了嗎?並沒有。這種方式只是簡單的前端路由控制,並不能真正阻止使用者訪問需要登入許可權的路由。還有一種情況便是:當前token失效了,但是token依然儲存在本地。這時候你去訪問需要登入許可權的路由時,實際上應該讓使用者重新登入。
這時候就需要結合 http 攔截器 + 後端介面返回的http 狀態碼來判斷。
第二步:攔截器
要想統一處理所有http請求和響應,就得用上 axios 的攔截器。通過配置http response inteceptor
,當後端介面返回401 Unauthorized(未授權)
,讓使用者重新登入。
// http request 攔截器
axios.interceptors.request.use(
config => {
if (store.state.token) { // 判斷是否存在token,如果存在的話,則每個http header都加上token
config.headers.Authorization = `token ${store.state.token}`;
}
return config;
},
err => {
return Promise.reject(err);
});
// http response 攔截器
axios.interceptors.response.use(
response => {
return response;
},
error => {
if (error.response) {
switch (error.response.status) {
case 401:
// 返回 401 清除token資訊並跳轉到登入頁面
store.commit(types.LOGOUT);
router.replace({
path: 'login',
query: {redirect: router.currentRoute.fullPath}
})
}
}
return Promise.reject(error.response.data) // 返回介面返回的錯誤資訊
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
完整的方法見
/src/http.js
.
通過上面這兩步,就可以在前端實現登入攔截了。登出
功能也就很簡單,只需要把當前token清除,再跳轉到首頁即可。
關於axios
對於axios,很多剛開始學習vue的人都覺得文件比較難以看懂。我剛開始也是這麼覺得的。但通過這麼一個專案下來後,發現axios並不難理解。建議在學習axios的時帶著下面的目的去看文件會更高效。因為掌握了下面這些內容,基本上就可以無障礙得在專案中使用axios了。
* 發起http請求的方法
* http 請求成功時返回的資料及其型別
* http請求失敗的處理
* 攔截器的使用
* http的配置
執行及構建
# install dependencies
npm install
# serve with hot reload at localhost:8080
npm run dev
# build for production with minification
npm run build
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
相關推薦
Vue+axios實現登陸攔截,axios封裝(報錯,鑑權,跳轉,攔截,提示)
axios封裝 需求及實現 統一捕獲介面報錯 彈窗提示 報錯重定向 基礎鑑權 表單序列化 實現的功能 統一捕獲介面報錯 : 用的axios內建的攔截器 彈窗提示: 引入 Element UI的Message元件 報錯重定向: 路由鉤子
給axios做個挺靠譜的封裝(報錯,鑑權,跳轉,攔截,提示
前言不推薦完全copy過去,可以看看我是如何針對我這邊業務;做的一個axios的封裝及實現的思路需求及實現統一捕獲介面報錯彈窗提示報錯重定向基礎鑑權表單序列化實現的功能統一捕獲介面報錯 : 用的axios內建的攔截器彈窗提示: 引入 Element UI的Message元件報錯重定向: 路由鉤子基礎鑑權: 服
在Eclipse上安裝外掛springsource-tool-suite詳解,完美不報錯!以及yml無自動提示?
在Eclipse上操作springboot過程中,開啟yml檔案時,為何沒有提示訊息? 答:提示訊息是需要eclipse的一個叫sts的外掛支援的。 為何在eclipse上線上安裝springsource-tool-suite外掛時,總報錯,安裝不成功? 那麼我們需要離
MySQL5.6 GTID模式,同步複製報錯不能跳過解決方法
搭建虛擬機器centos6.0, mysql5.6.10主從複製,死活不同步,搞了一整天找到這篇文章。終於OK了。 資料庫版本: mysql> select version(); +------------+ | version() | +----------
Vue-Axios外掛使用指南,封裝報錯、鑑權、跳轉、攔截
熟練使用axios框架,可以讓我們省去很多重複的、繞彎路多的寫法。 前言 不推薦完全copy過去,可以看看我是如何針對我這邊業務; 做的一個axios的封裝及實現的思路 需求及實現 統一捕獲 前言 不推薦完全copy過去,可以看看我是如何針對我這邊業務; 做的一個axi
Vue專案跨域設定,axios跨域不成功的一個小問題( Vue CLI3跨域請求,Vue proxyTable配置,Access-Control-Allow-Origin )
Vue專案,因為前後端分離,所以在請求後端介面時,時常遇到跨站問題, 2、如果前後端部署在同一個域名,就不會有跨域問題,但一般是生產環境部署是同一個域名下,但在開發環境時,並不是同域名呀,所以開發時呼叫介面返回類似“No 'Access-Control-Allow-Or
axios實現下載功能,伺服器之間進行檔案傳輸
需求描述: 需求其實很簡單就是檔案下載。 前端以下簡稱為:client 後端伺服器簡稱:oneServer 檔案所在伺服器簡稱:fileServer 解決方案 運用jcifs包中的SmbFile方法,oneServer只需要知道fileServ
vue+mousemove實現拖動,鼠標移動過快拖動就失效
拖動 win text cli prev point element lis 問題 今天用vue+原生js的mousemove事件,寫了個拖動,發現只能慢慢拖動才行,鼠標只要移動快了,就失效,不能拖動了; 搞了半天在,總算解決了,但是問題的深層原理還沒搞清楚,知道的大俠可以
Python實現京東登入,類封裝
直接執行輸入自己賬戶密碼即可登入,獲取資料 # 引入包 import time import requests from bs4 import BeautifulSoup class JD_crawl: def __init__(self, username, passw
實現登陸功能,登陸三次鎖定使用者
目標:實現登陸功能,登陸三次鎖定使用者,沒有資料庫,用txt文字實現 name.txt liubei|123456|3zhugeliang|654321|3zhangfei|123|3machao|321|3zhangsan|1122333|3lisi|1231|3 file1 =
Bmob實現登陸註冊,解決官方signUp與Success方法更新後出錯問題
今天用Bmob寫一個程式,發現官方給的登入註冊方法不對,檢視更新才發現問題。 官方文件給的註冊是這樣的 但你要這樣寫會發現報錯,那是因為新的BmobSDK更新了方法。 那麼新的我們該怎麼寫,程式
Spring Boot 搭建應用實現登陸例項,頁面使用bootstrap
Spring boot 搭建web應用集成了thymeleaf模板實現登陸 下面是pom.xml的配置 <?x
Spring Security4.1.3實現攔截登錄後向登錄頁面跳轉方式(redirect或forward)返回被攔截界面
response href tools 當前 錯誤 界面 sets view 鏈接 一、看下內部原理 簡化後的認證過程分為7步: 用戶訪問網站,打開了一個鏈接(origin url)。 請求發送給服務器,服務器判斷用戶請求了受保護的資源。
Vue 項目: npm run dev b報錯 “'webpack-dev-server' 不是內部或外部命令,也不是可運行的程序 或批處理文件。”
output 安裝 modules RR module -i progress his dev 前提: 電腦已經安裝了nodeJS和npm, 項目是直接下載的zip包。 報錯步驟為1:cd /d 目錄; 2. npm ren dev -------> 報錯如下:
vue頁面渲染完成,但console報錯
使用 v-for 迴圈顯示一個數組物件的屬性值,但無法獲取1級物件巢狀下的2級物件屬性值, 比如:{{ itemData.State.Name }} 這是因為頁面渲染的時候,VUE裡return出來的data資料裡還只有1級物件,還沒有2級物件的值。 解決的方法是給頁面的最外層di
1.問題一:在oracle中,連續十次嘗試登陸不成功,那麼此賬戶將會被鎖定(lock)。當使用被鎖定的賬戶登入時,系統會報錯:ORA-28000: the account is locked。
解決思路: 以管理員的身份登入,即以sys或者system登入資料庫; 使用命令解鎖使用者:alter user 這裡是使用者名稱 account unlock; 重置密碼:alter user 這裡是使用者名稱 identified by 這裡是重置的密碼; 重新登入即可。
vue,下級頁面刷新導致路由跳轉帶過來的數據消失的解決方法
導致 頁面 owa eof color query 刷新 轉化 pri if(typeof(this.$route.query.result)==‘string‘){ //刷新時走這 }else{ //正常路由跳轉過來後就把數據塞到 localStorage
Xposed框架開發入門(二)--使用Xposed框架實現Activity跳轉攔截
接著上一篇Xposed框架入門開發(一)繼續,在上一篇中已經說了,第二篇主要介紹的是Xposed框架開發的基礎的應用。在接下來的文章中,主要以一個Activity的跳轉APP為例, 示範Xposed框架的基本使用方法。 1、編寫一個簡單的Activity跳
vue專案,打包後報錯以及空白問題
第一次從無到有自己搭建vue專案,npm run dev完全正常,打包之後頁面空白且報錯檔案找不到 1.修改config下面的index.js assetsPublicPath預設的是 ‘/’ 也就是根目錄。而我們的index.html和static在同一級目錄下面。
vue頁面跳轉攔截器
登入攔截邏輯 第一步:路由攔截 首先在定義路由的時候就需要多新增一個自定義欄位requireAuth,用於判斷該路由的訪問是否需要登入。如果使用者已經登入,則順利進入路由, 否則就進入登入頁面。在路由管理頁面新增meta欄位 import Vue from 'vue'