Vue路由之JWT身份認證

Vue路由之JWT身份認證

1、JWT身份認證簡介

JSON Web Token(JWT)是目前最流行的 跨域身份驗證解決方案,相較於session機制, 服務器就不須要保存任何 session 數據了,也就是說, 服務器變成無狀態了,從而比較容易實現擴展。JWT 其實是一個令牌(Token),服務器會將一些 元數據指定的secret進行 簽名並生成token,並返回給客戶端,客戶端獲得這個服務器返回的令牌後,須要 將其存儲到 Cookie 或 localStorage 中,此後, 每次與服務器通訊都要帶上這個令牌,能夠把它放到 Cookie 中自動發送,但這樣作不能跨域,因此更好的作法是將其放到 HTTP 請求頭 Authorization 字段裏面。

2、JWT的使用

① 安裝並引入jsonwebtoken模塊;
② 對元數據secret密鑰進行簽名,並生成對應的token;
③ 對token進行校驗是否過時ios

const jwt = require("jsonwebtoken"); // 引入jwt
const secret = "this is a private key"; // 指定一個用於生成token的密鑰字符串
const token = jwt.sign({ foo: 'bar' }, secret, { // 傳入元數據和secret密鑰,並指定過時時間生成token
    expiresIn: 5, // 單獨一個數字表示多少秒
    // 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 已經失效了.');
        } else {
            console.log(`token data is ${JSON.stringify(decoded)}`);
        }
    });
}, 5000);
生成的token爲一個很長的字符串,分爲三部分,每部分由.號隔開,即 頭部.載荷.簽名,5秒後token校驗結果爲error,即token已通過期,校驗的時候,會獲得token的解碼數據,主要包括生成token時候的 元數據token的簽發時間(iat)token的過時時間(exp)
// 生成的token字符串爲
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJpYXQiOjE1NjY3MzE4MzEsImV4cCI6MTU2NjczMTgzNn0.cZZkExNnVqBtnfQN2vtU2Z7JB0PBo1CFyC5NiOywg54
// token decoded後的數據
token data is {"foo":"bar","iat":1566731831,"exp":1566731836}

3、封裝axios

因爲在使用jwt認證的時候,客戶端向服務器發起請求的時候, 都要帶上token,即要獲取到token並將其 放到請求頭的Authorization字段中,服務器才能從authorization中取出token並進行校驗,因此咱們必須經過 攔截器去實現,在每次請求以前將請求進行攔截,而後添加上token,再繼續向服務器發起請求。
import axios from "axios";
class Request {
    constructor() {
        this.baseURL = process.env.NODE_ENV === 'development' ? 'http://localhost:3000' : '/'; // 設置請求baseURL
        this.timeout = 2000; // 設置請求超時時間
    }
    request(config){// 這裏的config是請求的時候傳遞的參數配置對象,好比url、method、data等
        const instance = axios.create({ // 建立axios實例
            baseURL: this.baseURL,
            timeout: this.timeout,
        });
        // 設置攔截器
        instance.interceptors.request.use((config) => { // 請求攔截以後就是要使用這個config, config表示整個請求對象
            config.headers.Authorization = localStorage.getItem('token'); // 將token從localStorage中取出並添加到請求頭的Authorization字段上
            return config; // 返回請求對象,繼續向服務器發起請求
        }, err => Promise.reject(err));
        // 設置響應攔截器
        instance.interceptors.response.use(res => res.data, err => Promise.reject(err));
    
        return instance(config);
    }
}
export default new Request();

4、經過路由鉤子進行登陸校驗

咱們須要在路由跳轉以前,進行登陸校驗,即 校驗登陸的token是否已通過期,若是token沒有失效,則能夠繼續訪問頁面;若是token已經失效,那麼檢查一下 所訪問的頁面是否須要登陸才能訪問,若是是須要登陸後才能訪問,那麼跳轉到登陸頁面;若是是不須要登陸也能訪問的頁面則繼續訪問;
const whiteList = ["/"]; // 定義一個白名單列表
router.beforeEach(async (to, from, next) => {
  if (whiteList.includes(to.path)) { // 若是是訪問的白名單中的頁面
    return next(); // 不須要校驗,直接返回繼續訪問該頁面
  }
  const isTokenAvailable = await store.dispatch('validate'); // 校驗token是否失效
  if (isTokenAvailable) { // 若是token未失效
    if(to.path === "/login") { // 若是訪問的是login頁面,則回到首頁
      next("/");
    } else { // 若是訪問的不是login頁面,則繼續訪問當前要訪問的頁面
      next();
    }
  } else { // 若是token失效了
    const needLogin = to.matched.some(item => item.meta.needLogin); // 檢測要訪問的頁面是否須要登陸才能訪問
    if(needLogin) { // 若是訪問的頁面是須要登陸的
      next("/login"); // 跳轉到登陸頁面
    } else { // 若是訪問的頁面是不須要登陸的,則直接繼續訪問
      next();
    }
  }
});
上面item.meta.needLogin,這個needLogin是在router中進行自定義配置的,在配置路由的時候, 容許經過meta屬性配置一些自定義的元數據,以下所示:
export default new Router({
  routes: [
    {
      path: '/profile',
      name: 'profile',
      component: Profile,
      meta: {needLogin: true}
    }
  ]
})

5、總結

jwt認證,主要就是Vue路由鉤子 beforeEach()的應用,以及請求攔截器的封裝,在每次 路由跳轉前進行token認證(校驗),檢測token是否失效,其校驗過程就是 向服務器發起一個請求,好比"/validate",因爲客戶端請求 攔截器的做用,會在發起"/validate"請求以前,在請求頭的 Authorization字段加上token,服務器收到token後就能對token是否有效進行校驗了,而後返回token校驗結果, 客戶端再根據token的校驗結果進行路由的具體跳轉
相關文章
相關標籤/搜索