溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎么在Vue路由中實(shí)現(xiàn)JWT身份認(rèn)證

發(fā)布時(shí)間:2021-06-02 17:37:20 來源:億速云 閱讀:491 作者:Leah 欄目:web開發(fā)

怎么在Vue路由中實(shí)現(xiàn)JWT身份認(rèn)證?針對(duì)這個(gè)問題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡(jiǎn)單易行的方法。

一、JWT身份認(rèn)證簡(jiǎn)介

JSON Web Token(JWT)是目前最流行的跨域身份驗(yàn)證解決方案,相較于session機(jī)制,服務(wù)器就不需要保存任何 session 數(shù)據(jù)了,也就是說,服務(wù)器變成無狀態(tài)了,從而比較容易實(shí)現(xiàn)擴(kuò)展。JWT 實(shí)際上是一個(gè)令牌(Token),服務(wù)器會(huì)將一些元數(shù)據(jù)、指定的secret進(jìn)行簽名并生成token,并返回給客戶端,客戶端得到這個(gè)服務(wù)器返回的令牌后,需要將其存儲(chǔ)到 Cookie 或 localStorage 中,此后,每次與服務(wù)器通信都要帶上這個(gè)令牌,可以把它放到 Cookie 中自動(dòng)發(fā)送,但這樣做不能跨域,所以更好的做法是將其放到 HTTP 請(qǐng)求頭 Authorization 字段里面。

二、JWT的使用

① 安裝并引入jsonwebtoken模塊;
② 對(duì)元數(shù)據(jù)、secret密鑰進(jìn)行簽名,并生成對(duì)應(yīng)的token;
③ 對(duì)token進(jìn)行校驗(yàn)是否過期;

const jwt = require("jsonwebtoken"); // 引入jwt
const secret = "this is a private key"; // 指定一個(gè)用于生成token的密鑰字符串
const token = jwt.sign({ foo: 'bar' }, secret, { // 傳入元數(shù)據(jù)和secret密鑰,并指定過期時(shí)間生成token
  expiresIn: 5, // 單獨(dú)一個(gè)數(shù)字表示多少秒
  // expiresIn: "10h", // 表示10小時(shí)后過期
  // expiresIn: "2d" // 表示2天后過期
});
console.log(`token is ${token}`);
setTimeout(() => { // 5秒后對(duì)該token進(jìn)行校驗(yàn)
  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為一個(gè)很長(zhǎng)的字符串,分為三部分,每部分由.號(hào)隔開,即 頭部.載荷.簽名,5秒后token校驗(yàn)結(jié)果為error,即token已經(jīng)過期,校驗(yàn)的時(shí)候,會(huì)得到token的解碼數(shù)據(jù),主要包括生成token時(shí)候的元數(shù)據(jù)、token的簽發(fā)時(shí)間(iat)、token的過期時(shí)間(exp)

// 生成的token字符串為
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJpYXQiOjE1NjY3MzE4MzEsImV4cCI6MTU2NjczMTgzNn0.cZZkExNnVqBtnfQN2vtU2Z7JB0PBo1CFyC5NiOywg54
// token decoded后的數(shù)據(jù)
token data is {"foo":"bar","iat":1566731831,"exp":1566731836}

三、封裝axios

由于在使用jwt認(rèn)證的時(shí)候,客戶端向服務(wù)器發(fā)起請(qǐng)求的時(shí)候,都要帶上token,即要獲取到token并將其放到請(qǐng)求頭的Authorization字段中,服務(wù)器才能從authorization中取出token并進(jìn)行校驗(yàn),所以我們必須通過攔截器去實(shí)現(xiàn),在每次請(qǐng)求之前將請(qǐng)求進(jìn)行攔截,然后添加上token,再繼續(xù)向服務(wù)器發(fā)起請(qǐng)求。

import axios from "axios";
class Request {
  constructor() {
    this.baseURL = process.env.NODE_ENV === 'development' ? 'http://localhost:3000' : '/'; // 設(shè)置請(qǐng)求baseURL
    this.timeout = 2000; // 設(shè)置請(qǐng)求超時(shí)時(shí)間
  }
  request(config){// 這里的config是請(qǐng)求的時(shí)候傳遞的參數(shù)配置對(duì)象,比如url、method、data等
    const instance = axios.create({ // 創(chuàng)建axios實(shí)例
      baseURL: this.baseURL,
      timeout: this.timeout,
    });
    // 設(shè)置攔截器
    instance.interceptors.request.use((config) => { // 請(qǐng)求攔截之后就是要使用這個(gè)config, config表示整個(gè)請(qǐng)求對(duì)象
      config.headers.Authorization = localStorage.getItem('token'); // 將token從localStorage中取出并添加到請(qǐng)求頭的Authorization字段上
      return config; // 返回請(qǐng)求對(duì)象,繼續(xù)向服務(wù)器發(fā)起請(qǐng)求
    }, 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();

四、通過路由鉤子進(jìn)行登錄校驗(yàn)

我們需要在路由跳轉(zhuǎn)之前,進(jìn)行登錄校驗(yàn),即校驗(yàn)登錄的token是否已經(jīng)過期,如果token沒有失效,則可以繼續(xù)訪問頁(yè)面;如果token已經(jīng)失效,那么檢查一下所訪問的頁(yè)面是否需要登錄才能訪問,如果是需要登錄后才能訪問,那么跳轉(zhuǎn)到登錄頁(yè)面;如果是不需要登錄也能訪問的頁(yè)面則繼續(xù)訪問;

const whiteList = ["/"]; // 定義一個(gè)白名單列表
router.beforeEach(async (to, from, next) => {
 if (whiteList.includes(to.path)) { // 如果是訪問的白名單中的頁(yè)面
  return next(); // 不需要校驗(yàn),直接返回繼續(xù)訪問該頁(yè)面
 }
 const isTokenAvailable = await store.dispatch('validate'); // 校驗(yàn)token是否失效
 if (isTokenAvailable) { // 如果token未失效
  if(to.path === "/login") { // 如果訪問的是login頁(yè)面,則回到首頁(yè)
   next("/");
  } else { // 如果訪問的不是login頁(yè)面,則繼續(xù)訪問當(dāng)前要訪問的頁(yè)面
   next();
  }
 } else { // 如果token失效了
  const needLogin = to.matched.some(item => item.meta.needLogin); // 檢測(cè)要訪問的頁(yè)面是否需要登錄才能訪問
  if(needLogin) { // 如果訪問的頁(yè)面是需要登錄的
   next("/login"); // 跳轉(zhuǎn)到登錄頁(yè)面
  } else { // 如果訪問的頁(yè)面是不需要登錄的,則直接繼續(xù)訪問
   next();
  }
 }
});

上面item.meta.needLogin,這個(gè)needLogin是在router中進(jìn)行自定義配置的,在配置路由的時(shí)候,允許通過meta屬性配置一些自定義的元數(shù)據(jù),如下所示:

export default new Router({
 routes: [
  {
   path: '/profile',
   name: 'profile',
   component: Profile,
   meta: {needLogin: true}
  }
 ]
})

關(guān)于怎么在Vue路由中實(shí)現(xiàn)JWT身份認(rèn)證問題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI