vue項目結合vuex、localstorage實現本地儲存token驗證登陸注冊


  • 首次登錄時,后端服務器判斷用戶賬號密碼正確之后,根據用戶id、用戶名、定義好的秘鑰、過期時間生成 token ,返回給前端;
  • 前端拿到后端返回的 token ,存儲在 localStroage 和 Vuex 里;
  • 前端每次路由跳轉,判斷 localStroage 有無 token ,沒有則跳轉到登錄頁,有則請求獲取用戶信息,改變登錄狀態;
  • 每次請求接口,在 Axios 請求頭里攜帶 token;
  • 后端接口判斷請求頭有無 token,沒有或者 token 過期,返回401;
  • 前端得到 401 狀態碼,重定向到登錄頁面。

store.js

import Vue from 'vue'
import Vuex from 'vuex'
import VuexPersistence from 'vuex-persist'

Vue.use(Vuex)
const vuexLocal = new VuexPersistence({
  storage: window.localStorage,
  reducer: state => ({
    token: state.token, // 這個就是存入localStorage的值
    WXTempKey: state.WXTempKey
  })
})
const store = new Vuex.Store({
  state: {
    token: "",
    WXTempKey: '',
    isLogin: false,
    uid: 0,
    name: '',
    avatar: ''
  },
  mutations: {
    setToken(state, token) {
      state.token = token
    },
    setLogin(state, flag) {
      state.isLogin = flag
    },
    setWXTempKey(state, WXTempKey) {
      state.WXTempKey = WXTempKey
    },
  },

  actions: {},
  plugins: [vuexLocal.plugin]
})

export default store

 

 登陸頁

    // 登陸方法
    async login() {
      if (!this.phone || !this.password) {
        // this.$toasted.error("請輸入完善信息", { icon: "error" }).goAway(2000);
        Notify({ type: 'danger', message: "請輸入完善信息", duration: 1500 })
        return;
      }
      
      try {
        // await等待一個異步返回的結果 如果沒有await 會報user is undefined 獲取不到
        let res = await this.http.post("/api/TokenAuth/MemberAuthenticate", {
          Phone: this.phone,
          PhoneCode: this.password,
          WXTempKey: this.$store.state.WXTempKey
            ? this.$store.state.WXTempKey
            : ""
        });
        console.log(res);
        if (res.Result) {
          // debugger
          // console.log(res);
          // localStorage.setItem("token","res.Result.AccessToken");
          this.$store.commit("setToken", res.Result.AccessToken);
          Toast({
            mask: false,
            message: '登錄成功',
            position: 'bottom'
          });
          this.$router.replace({ name: "index" });
        } else {
          // this.$toasted
          //   .error(res.Error.Message, { icon: "error" })
          //   .goAway(2000);
        }
      } catch (error) {
        // this.$toasted.error(error.message, { icon: "error" }).goAway(2000);
      }
    }

http.js

import axios from 'axios'
import store from './store'
import { getToken } from '@/util/token'
import qs from 'qs'
import config from './config'
import router from './router'
import Vue from 'vue'
import VuexPersistence from 'vuex-persist'
import { Notify,Toast } from 'vant'

console.log(config)

// 創建axios實例
const http = axios.create({
  baseURL: config.api_base,
  timeout: 15000,
 //設置請求頭
  headers: {
    // 'Content-Type': 'application/x-www-form-urlencoded'
    'Content-Type' : 'application/json',
  }
//利用qs解析json數據讓后端可以解析
  transformRequest: [
      function(data, headers) {
        data = data || {}
        data = qs.stringify(data)
        return data
      }
    ]
})

// request攔截器
http.interceptors.request.use(config => {
  config.data = config.data ? config.data : {}
  config.headers["authorization"] =store.state.token; //把token添加到請求頭每次請求接口時候帶上
if(config.method=='get'){
    Toast({
      mask: false,
      message: '加載中...',
      position: 'bottom'
    });
  }else{
    Toast.loading({
      mask: true,
      message: '加載中...',
      position: 'middle',
      loadingType:'spinner'
    });
  }
  if (router.currentRoute && router.currentRoute.meta.requiresAuth) {
    if (localStorage.getItem('user')) {
      return Promise.reject('請登錄后操作')
    } else {

      // config.headers.Authorization = token;

      // config.headers['authorization'] = `${store.state.token}`;
        console.log('interceptors config=',config)
      return config
    }
  } else {
    return config
  }
})

// respone攔截器
http.interceptors.response.use(
  response => {
    let data = response.data

    let msg = data.message || ''
    Toast.clear();
    if (response.status === 200) {
      if (response.data.Result) {
        if (response.data.Result.Code && response.data.Result.Code !== 0) {
          Notify({ type: 'danger', message: response.data.Result.Message, duration: 1500 })
          return Promise.resolve(response.data)
        } else {
          return Promise.resolve(response.data)
        }
      }else
      {
        return Promise.resolve(response.data)   
      }
    } else {
      Notify({ type: 'danger', message: '請求失敗,請稍后再試!!!', duration: 1500 })
      return Promise.reject(response)
    }

    // if (data.code == 401) {
    //   // 賬號禁用
    //   Vue.toasted.error(data.message, { icon: 'error' }).goAway(2000)
    //   router.replace({ name: 'login' })
    //   return Promise.reject(new Error(msg))
    // } else if (data.code == 403) {
    //   // 登錄失效 需重新登錄
    //   Vue.toasted.error('登錄失效 需重新登錄', { icon: 'error' }).goAway(2000)
    //   router.replace({ name: 'login' })
    //   return Promise.reject(new Error(msg))
    // } else if (data.code == 400) {
    //   return Promise.reject(new Error(msg))
    // }
    // return data
  },
  err => {
    Toast.clear();
    if (err.response.data.Error) {
      Notify({ type: 'danger', message: err.response.data.Error.Message, duration: 1500 })
      if(err.response.status == 401 || (err.response.data.Error && err.response.data.Error.Code)){
        console.log(router)
        store.commit("setToken", '');
        router.push({
            path: "/login",
            query:{
              redirect:router.currentRoute.fullPath
            }
        });
      }
    } else {
      Notify({ type: 'danger', message: '請求失敗!!!', duration: 1500 })
    }
    return Promise.reject(err)
  }
)

export default http

 


免責聲明!

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



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