Vue 項目 login 模塊


登錄模塊

需要做路由的守衛,有些模塊是需要被保護的,必須登錄才能訪問。 常見手法是給路由添加 meta:{ auth:true } 來做標識,表示需要做認證。

// 路由守衛
router.beforeEach((to, from, next) => {
    // 判斷要進入的路由是否需要認證
    if(to.meta.auth) {
        // 通過token令牌機制判斷是否已經登錄
        const token = localStorage.getItem('token');
        if (token) {
            next(); // 如果登錄則放行,進入路由
        } else {
        	// 跳轉,並攜帶重定向地址
            next({
               path: '/login', 
               query: {
                   redirect: to.path 
               }
            });
        }
    } else {
        // 不需要驗證的模塊,直接放行
        next();
    }
});

在 Vuex 中存儲登錄狀態 isLogin

import Vue from 'vue'
import Vuex from 'vuex'
import user from './service/user'

Vue.use(Vuex);
export default new Vuex.Store({
    state: {
        isLogin: localStorage.getItem('token') ? true : false
    },
    mutations: {
        setLoginState(state, bool) {
            state.isLogin = bool;
            // true 表示登錄,false 表示注銷
        }
    },
    actions: {
        login({commit}, user) {
            // 發起登錄請求,請求都拆分出去 service 文件夾中
            // 使用 service 的請求方法
            user.login(user).then(res => {
                // 從 res.data 中解構數據,code和token
                const { code, token } = res.data;
                if (code) {
                    // 登錄成功,修改Vuex中間的登錄狀態
                    commit('setLoginState', true);
                    // 緩存令牌 token
                    localStorage.setItem("token", token);
                }
                return code; // 返回code 給下一個 .then 使用
            });
        },
        logout({ commit }) {
            // 清除緩存
            localStorage.removeItem('token');
            // 重置狀態
            commit('setLoginState', false);
        }
    }
});

service文件夾下的服務

// 返回一個 Promises 方便外面使用
import axios from 'axios'
export default {
    login(user) {
    	// 注意:請求地址最好是抽出去統一管理
        return axios.get('/api/login', { 
        	params: user 
        });
    }
}

登錄組件中提交事件處理過程

// 提交函數中, dispatch 是調用 actios 中的方法,在通過 commit 發送 mutations 方法修改數據
// 注意:this.model 就是傳遞的數據
this.$store.dispatch("login", this.model)
	.then(code => {
        if (code) {
            // 登錄成功后,重定向,如果沒有則重定向到首頁
            const path = this.$route.query.redirect || '/';
            this.$router.push(path);
        }
	}).catch(error => {
        // 有錯誤發生 或 登錄失敗
        const toast = this.$createToast({
            time: 2000,
            text: error.message || error.response.data.message || "登錄失敗",
            type: "error"
        });
        toast.show();
	});

需要考慮的檢查點

  • 如何守衛路由
  • 如何進行異步操作
  • 如何保存登錄狀態
  • 如何模擬接口

HTTP 攔截器

新建 interceptor.js 文件,用於攔截請求和響應

// token 過期導致請求失敗的情況可能出現在項目的任何地方,可以通過響應攔截統一處理
// 攔截器的作用:是對接口做一層保護,表示所有的接口都會帶有令牌 token  
// 可以查看 axios 的文檔 : http://www.axios-js.com/zh-cn/docs/
const axios = require('axios');

export default function(vm) {
	// HTTP 請求攔截器
    axios.interceptors.request.use(config => {
        // 在發送請求之前做些什么
        // 獲取token, 並添加到 headers 請求頭中
        const token = localStorage.getItem('token');
        if (token) {
            config.headers.token = token;
        }
        return config;
    });
    
    // HTTP 響應攔截器
    // 統一處理 401 狀態,token 過期的處理,清除token跳轉login 
    // 參數 1, 表示成功響應
    axios.interceptors.response.use(null, err => {
        // 沒有登錄或令牌過期
        if (err.response.status === 401) {
            // 注銷,情況狀態和token
            vm.$store.dispatch("logout");
            // 跳轉的登錄頁
            vm.$storer.push('/login');
            // 注意: 這里的 vm 實例需要外部傳入
        }
        return Promise.reject(err);
    });
}

// 使用攔截器
// 1. 引入攔截器文件
import interceptor from './interceptor'
// 執行攔截器初始化
interceptor(vm);

注銷

  • 需要清除 token 緩存的兩種情況:
    1. 用戶主動注銷
    2. token 過期
  • 需要做的事情:
    • 清空緩存
    • 重置登錄狀態
methods: {
    logout() {
        this.$route.dispatch('login');
    }
}

深入理解令牌機制

  • Bearer Token規范

    • 概念: 描述在HTTP訪問OAuth2保護資源時如何使用令牌的規范
    • 特點:令牌就是身份證,無需證明令牌的所有權
    • 具體規定:在請求頭中定義Auuthorization:Bearer token
  • Json Web Token 規范 https://jwt.io

    • 概念:令牌的具體定義方式
    • 規定:令牌由三部分構成 頭、載荷、簽名
    • 頭:包含加密算法、令牌類型等信息
    • 載荷:包含用戶信息、簽發時間和過期時間等信息
    • 簽名:根據頭、載荷及秘鑰加密得到的哈希串

滴滴 Cube-UI 庫 精致的移動端組件庫

Cube-UI 庫地址


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM