vue項目中的登錄鑒權


  用vue做一個簡單的登錄鑒權功能。

項目目錄結構如下:

 

Login 組件

  登錄成功后做本地存儲和store存儲,並進行跳轉。

Login.vue關鍵代碼:

    async handleLogin(e) {
      e.preventDefault();
      let parmas = {
        username: this.model.username,
        passwold: this.model.passwold
      };
      const res = await this.$http.get("/api/login", parmas);
      const { code, token, massage } = res.data;
      //code=='0'表示登錄成功,進行本地存儲和store存儲 並進行跳轉。
      //else 彈出錯誤提示
      if (code == "0") {
        this.$store.commit("setToken", res.data.token);
        localStorage.setItem("token", token);
        //如果是由需要鑒權的頁面跳轉到登錄頁面 則redirect= this.$route.query.redirect,如果是直接點擊登錄跳轉到登錄頁面,則redirect= '/'
        const redirect = this.$route.query.redirect || "/";
        this.$router.push(redirect);
      } else {
        const toast = this.$createToast({
          time: 2000,
          txt: massage || "登錄失敗",
          type: "error"
        });
        toast.show();
      }
    }

store

  在Login組件里登錄時token做了數據持久化處理,防止頁面刷新丟失token。給store里的token賦初值的時候要取

store.js關鍵代碼:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    //token數據持久化,防止頁面刷新丟失
    token: localStorage.getItem('token') || ''
  },
  mutations: {
    setToken(state, token) {
      state.token = token
    }
  },
  actions: {

  },
  getters: {
    //根據token是否存在,設置計算屬性isLogin
    isLogin(state) {
      return !!state.token
    }
  }
})

router

  routes[]里用 mate.auth來標識是否需要鑒權。router.beforeEach做個全局路由守衛,根據是否需要鑒權以及是否已經登錄來進行不同操作。

router.js代碼:

import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'
import Login from './views/Login.vue';
import store from './store';
Vue.use(Router)

const router = new Router({
  mode: 'history',
  base: process.env.BASE_URL,
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    },
    {
      path: '/login',
      name: 'login',
      component: Login
    },
    {
      path: '/about',
      name: 'about',
      meta: { auth: true },//about需要做登錄鑒權
      component: () => import(/* webpackChunkName: "about" */ './views/About.vue')
    }
  ]
})
router.beforeEach((to, from, next) => {
  //to.meta.auth 表示需要做登錄健全
  //不需要的 可以直接next
  if (to.meta.auth) {
    //store.state.token 表示已經登錄 可以直接next
    //沒有登錄 跳轉到/login 並攜帶參數redirect 方便登錄后直接跳轉到to.path
    if (store.state.token) {
      next();
    } else {
      next({
        path: '/login',
        query: { redirect: to.path }
      })
    }
  } else {
    next();
  }
})
export default router;

axios攔截  

  axios.interceptors.request.use攔截axios所有http請求,如果存在token,則放入請求頭。axios.interceptors.response.use攔截的axios的響應,如果token以及失效,則清除本地緩存和store存儲並跳轉到登錄頁面。

http-interceptors.js代碼:

import axios from "axios";
import store from "./store";
import router from "./router";
// 攔截axios所有http請求,預先放入token請求頭
axios.interceptors.request.use(config => {
  if (store.state.token) {
    // 若存在token,則放入請求頭
    config.headers.token = store.state.token;
  }
  return config;
});

// 響應攔截器,提前預處理響應
axios.interceptors.response.use(
  response => {
    // 如果code是-1,說明用戶已注銷或者token已過期
    // 此時需要重新登錄,並且還要清除本地緩存信息和store數據
    if (response.status == 200) {
      const data = response.data;
      if (data.code == -1) {
        logoutFun()
      }
    }
    return response;
  },
  err => {
    if (err.response.status === 401) { // 未授權
      logoutFun()
    }
  }
);

function logoutFun() {
  // 清空本地緩存的token和store里的token
  store.commit("setToken", "");
  localStorage.removeItem("token");
  // 跳轉至登錄頁,並攜帶用戶退出時或token失效時的頁面路由,方便登錄后直接跳轉到此頁面。
  router.push({
    path: "/login",
    query: {
      redirect: router.currentRoute.path
    }
  });
}

 

服務端中間件
  服務端也需要做請求處理的中間件。如果請求不是req.path不是'/api/login'並且沒有攜帶token,則返回錯誤狀態碼401。
vue.config.js關鍵代碼:
        app.use((req, res, next) => {
          //只對api開頭的請求做攔截處理
          if (/^\/api/.test(req.path)) {
            if (req.path == '/api/login' || req.headers.token) {
              next();
            } else {
              //設置錯誤狀態碼為401
              res.sendStatus('401')
              next();
            }
          } else {
            next();
          }
        })

 


免責聲明!

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



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