Vue路由之JWT身份認證的實現(xiàn)方法
一、JWT身份認證簡介
JSON Web Token(JWT)是目前最流行的跨域身份驗證解決方案,相較于session機制,服務(wù)器就不需要保存任何 session 數(shù)據(jù)了,也就是說,服務(wù)器變成無狀態(tài)了,從而比較容易實現(xiàn)擴展。JWT 實際上是一個令牌(Token),服務(wù)器會將一些元數(shù)據(jù)、指定的secret進行簽名并生成token,并返回給客戶端,客戶端得到這個服務(wù)器返回的令牌后,需要將其存儲到 Cookie 或 localStorage 中,此后,每次與服務(wù)器通信都要帶上這個令牌,可以把它放到 Cookie 中自動發(fā)送,但這樣做不能跨域,所以更好的做法是將其放到 HTTP 請求頭 Authorization 字段里面。
二、JWT的使用
① 安裝并引入jsonwebtoken模塊;
② 對元數(shù)據(jù)、secret密鑰進行簽名,并生成對應(yīng)的token;
③ 對token進行校驗是否過期;
const jwt = require("jsonwebtoken"); // 引入jwt const secret = "this is a private key"; // 指定一個用于生成token的密鑰字符串 const token = jwt.sign({ foo: 'bar' }, secret, { // 傳入元數(shù)據(jù)和secret密鑰,并指定過期時間生成token expiresIn: 5, // 單獨一個數(shù)字表示多少秒 // expiresIn: "10h", // 表示10小時后過期 // expiresIn: "2d" // 表示2天后過期 }); console.log(`token is ${token}`); setTimeout(() => { // 5秒后對該token進行校驗 jwt.verify(token, secret, (err, decoded) => { console.log(err); if (err) { console.log('token 已經(jīng)失效了.'); } else { console.log(`token data is ${JSON.stringify(decoded)}`); } }); }, 5000);
生成的token為一個很長的字符串,分為三部分,每部分由.號隔開,即 頭部.載荷.簽名,5秒后token校驗結(jié)果為error,即token已經(jīng)過期,校驗的時候,會得到token的解碼數(shù)據(jù),主要包括生成token時候的元數(shù)據(jù)、token的簽發(fā)時間(iat)、token的過期時間(exp)
// 生成的token字符串為 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJpYXQiOjE1NjY3MzE4MzEsImV4cCI6MTU2NjczMTgzNn0.cZZkExNnVqBtnfQN2vtU2Z7JB0PBo1CFyC5NiOywg54
// token decoded后的數(shù)據(jù) token data is {"foo":"bar","iat":1566731831,"exp":1566731836}
三、封裝axios
由于在使用jwt認證的時候,客戶端向服務(wù)器發(fā)起請求的時候,都要帶上token,即要獲取到token并將其放到請求頭的Authorization字段中,服務(wù)器才能從authorization中取出token并進行校驗,所以我們必須通過攔截器去實現(xiàn),在每次請求之前將請求進行攔截,然后添加上token,再繼續(xù)向服務(wù)器發(fā)起請求。
import axios from "axios"; class Request { constructor() { this.baseURL = process.env.NODE_ENV === 'development' ? 'http://localhost:3000' : '/'; // 設(shè)置請求baseURL this.timeout = 2000; // 設(shè)置請求超時時間 } request(config){// 這里的config是請求的時候傳遞的參數(shù)配置對象,比如url、method、data等 const instance = axios.create({ // 創(chuàng)建axios實例 baseURL: this.baseURL, timeout: this.timeout, }); // 設(shè)置攔截器 instance.interceptors.request.use((config) => { // 請求攔截之后就是要使用這個config, config表示整個請求對象 config.headers.Authorization = localStorage.getItem('token'); // 將token從localStorage中取出并添加到請求頭的Authorization字段上 return config; // 返回請求對象,繼續(xù)向服務(wù)器發(fā)起請求 }, err => Promise.reject(err)); // 設(shè)置響應(yīng)攔截器 instance.interceptors.response.use(res => res.data, err => Promise.reject(err)); return instance(config); } } export default new Request();
四、通過路由鉤子進行登錄校驗
我們需要在路由跳轉(zhuǎn)之前,進行登錄校驗,即校驗登錄的token是否已經(jīng)過期,如果token沒有失效,則可以繼續(xù)訪問頁面;如果token已經(jīng)失效,那么檢查一下所訪問的頁面是否需要登錄才能訪問,如果是需要登錄后才能訪問,那么跳轉(zhuǎn)到登錄頁面;如果是不需要登錄也能訪問的頁面則繼續(xù)訪問;
const whiteList = ["/"]; // 定義一個白名單列表 router.beforeEach(async (to, from, next) => { if (whiteList.includes(to.path)) { // 如果是訪問的白名單中的頁面 return next(); // 不需要校驗,直接返回繼續(xù)訪問該頁面 } const isTokenAvailable = await store.dispatch('validate'); // 校驗token是否失效 if (isTokenAvailable) { // 如果token未失效 if(to.path === "/login") { // 如果訪問的是login頁面,則回到首頁 next("/"); } else { // 如果訪問的不是login頁面,則繼續(xù)訪問當(dāng)前要訪問的頁面 next(); } } else { // 如果token失效了 const needLogin = to.matched.some(item => item.meta.needLogin); // 檢測要訪問的頁面是否需要登錄才能訪問 if(needLogin) { // 如果訪問的頁面是需要登錄的 next("/login"); // 跳轉(zhuǎn)到登錄頁面 } else { // 如果訪問的頁面是不需要登錄的,則直接繼續(xù)訪問 next(); } } });
上面item.meta.needLogin,這個needLogin是在router中進行自定義配置的,在配置路由的時候,允許通過meta屬性配置一些自定義的元數(shù)據(jù),如下所示:
export default new Router({ routes: [ { path: '/profile', name: 'profile', component: Profile, meta: {needLogin: true} } ] })
五、總結(jié)
jwt認證,主要就是Vue路由鉤子beforeEach()的應(yīng)用,以及請求攔截器的封裝,在每次路由跳轉(zhuǎn)前進行token認證(校驗),檢測token是否失效,其校驗過程就是向服務(wù)器發(fā)起一個請求,比如"/validate",由于客戶端請求攔截器的作用,會在發(fā)起"/validate"請求之前,在請求頭的Authorization字段加上token,服務(wù)器收到token后就能對token是否有效進行校驗了,然后返回token校驗結(jié)果,客戶端再根據(jù)token的校驗結(jié)果進行路由的具體跳轉(zhuǎn)。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
vue在標(biāo)簽中如何使用(data-XXX)自定義屬性并獲取
這篇文章主要介紹了vue在標(biāo)簽中如何使用(data-XXX)自定義屬性并獲取,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08Vue子組件props從父組件接收數(shù)據(jù)并存入data
這篇文章主要介紹了Vue子組件props從父組件接收數(shù)據(jù)并存入data的方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08Vue綁定class和綁定內(nèi)聯(lián)樣式的實現(xiàn)方法
本文主要介紹了Vue綁定class和綁定內(nèi)聯(lián)樣式的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-11-11Vue中使用element-ui給按鈕綁定一個單擊事件實現(xiàn)點擊按鈕就彈出dialog對話框
最近遇到了個需求是使用element-ui插件編寫頁面,點擊按鈕,彈出對話框,這篇文章主要給大家介紹了關(guān)于Vue中使用element-ui給按鈕綁定一個單擊事件實現(xiàn)點擊按鈕就彈出dialog對話框的相關(guān)資料,需要的朋友可以參考下2022-11-11el-upload http-request使用 多個文件上傳攜帶其他參數(shù)方式
這篇文章主要介紹了el-upload http-request使用 多個文件上傳攜帶其他參數(shù)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-04-04解決vue js IOS H5focus無法自動彈出鍵盤的問題
今天小編就為大家分享一篇解決vue js IOS H5focus無法自動彈出鍵盤的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08