1. 程式人生 > >vue+vuex+axios做登入、註冊頁許可權攔截

vue+vuex+axios做登入、註冊頁許可權攔截

在GitHub上有很多寫好的模板,這個專案也是基於模板做的。

現在記錄一下我做的過程

1、修改config資料夾裡的dev.env.js裡的BASE_API,把地址改成請求後端的公共部分

BASE_API: '"http://192.168.xx.xx"',

2、接下來就是操作src檔案,先在 views裡寫好vew元件(login.vue,regist.vue),寫好到router裡的index.js裡配置好路徑

login.vue

<template>
  <div class="login-container">
        <el-form autoComplete="on" :model="loginForm" :rules="loginRules" ref="loginForm" label-position="left"
                 label-width="0px"
                 class="card-box login-form">
          <h3 class="title">登入</h3>
            <el-form-item prop="name">
        <span class="svg-container svg-container_login">
          <svg-icon icon-class="user"/>
        </span>
              <el-input name="name" disabled type="text" v-model="loginForm.name" autoComplete="on"
                        placeholder="使用者名稱"/>
            </el-form-item>
            <el-form-item prop="password">
        <span class="svg-container">
          <svg-icon icon-class="password"></svg-icon>
        </span>
              <el-input name="password" :type="pwdType" @keyup.enter.native="handleLogin" v-model="loginForm.password"
                        autoComplete="on"
                        placeholder="密碼"></el-input>
              <span class="show-pwd" @click="showPwd"><svg-icon icon-class="eye"/></span>
            </el-form-item>
            <el-form-item>
              <el-button type="primary" style="width:100%;" :loading="loading" @click.native.prevent="handleLogin">
                登入
              </el-button>
            </el-form-item>
        </el-form>
      </div>
</template>

<script>
  export default {
    name: 'login',
    data() {
      const validateUsername = (rule, value, callback) => {
        if (value.trim().length<1) {
          callback(new Error('使用者名稱不能為空'))
        } else {
          callback()
        }
      };
      const validatePass = (rule, value, callback) => {
        if (value.trim().length < 1) {
          callback(new Error('密碼不能為空'))
        } else {
          callback()
        }
      };
      return {
        loginForm: {
          name: '',
          password: ''
        },
        loginRules: {
          name: [{required: true, trigger: 'blur', validator: validateUsername}],
          password: [{required: true, trigger: 'blur', validator: validatePass}]
        },
        loading: false,
        pwdType: 'password'
      }
    },
    methods: {
      showPwd() {
        if (this.pwdType === 'password') {
          this.pwdType = ''
        } else {
          this.pwdType = 'password'
        }
      },
      handleLogin() {
        this.$refs.loginForm.validate(valid => {
          if (valid) {
            this.loading = true;
            this.$store.dispatch('Login', this.loginForm).then(() => {
              this.loading = false;
              this.$router.push({path: '/'});
            }).catch((e) => {
              this.loading = false
            })
          } else {
            console.log('error submit!!')
            return false
          }
        })
      }
    }
   }
</script>

router/index.js

{ path: '/login', component: _import('Login/login'), hidden: true }

3、在api裡的login.js裡寫好與後端對接的介面地址,在stores裡的modules裡的user.js裡定義user,有state,mutations,action,具體的請求操作寫在action裡,login.vue或regist.vue呼叫user.js裡寫好的請求,getter.js裡定義store的getters

api/login.js

import request from '@/utils/request'
export function login(name,password) {
  return request({
    url: '/XX/XX',
    method: 'post',
    data: {
      name,
      password
    } 
  })
}

stores/modules/user.js

      import { login,regist,logout } from '@/api/login'
      import { getToken,setToken } from '@/utils/auth'

      const user = {
        state: {
          name:'',
          token:''
        },

        mutations: {
          SET_NAME: (state, name) => {
            state.name = name;
          },
          SET_TOKEN: (state, token) => {
            state.token = token;
            setToken(token);
          }
        },

        actions: {
          // 登入
          Login({ commit }, userInfo) {
            const name = userInfo.name.trim();
            const password = userInfo.password.trim();
            return new Promise((resolve, reject) => {
              login(name, password).then(response => {
                const data = response.data;
                commit('SET_NAME', data.name);
                commit('SET_TOKEN', data.token);
                setName(data.name);
                setToken(data.token);
                resolve(response); }).catch(error => { reject(error) }) }) },
          // 註冊 
          Regist({ commit }, userInfo) { 
            const name= userInfo.name.trim(); 
            const password = userInfo.password.trim(); 
            return new Promise((resolve, reject) => { 
              regist(name, password).then(response => { 
                const data = response.data; 
                commit('SET_NAME', data.name); 
                commit('SET_TOKEN', data.token);
                setName(data.name);setToken(data.token); 
                resolve(response);
              }).catch(error => { 
                reject(error) }) }) }, 
          // 登出 
          LogOut({ commit, state }) {
          return new Promise((resolve, reject) => {
            logout().then(response => {
              commit('SET_NAME', '');
              commit('SET_TOKEN', '');
              setName('');
              setToken(false);
              //removeName();
              //removeToken();
              resolve(response);
            }).catch(error => {
              reject(error)
            })
          })
        }, 
          // 前端 登出 
          FedLogOut({ commit }) { 
            return new Promise(resolve => {
        setToken(false);
    commit('SET_TOKEN', false);
    resolve()
            })
          }
        }
      }
      export default user
getter.js:
const getters={
 name:state=>state.user.name,
 token:state=>state.user.token
}
export default getter
4、在utils裡的auth.js裡對cookies進行操作,寫入,讀取,刪除使用者許可權,是否登入的標誌等
import Cookies from 'js-cookies'
export function setName(name) {
  return Cookies.set("name", name);
}
export function getName() {
  return Cookies.get("name");
}
export function setToken(token) {
  return Cookies.set("token", token);
}
export function getToken() {
  return Cookies.get("token");
}
5、在permission.js裡寫白名單,對白名單以外的跳轉進行攔截然後跳轉登入,同時判斷使用者許可權,是否登入,等

import router from './router'
import store from './store'
import NProgress from 'nprogress' // Progress 進度條
import 'nprogress/nprogress.css'// Progress 進度條樣式
import {Message} from 'element-ui'
import {getName, getToken} from "@/utils/auth"; // 驗權


const whiteList = ['/login', '/regist']; // 不重定向白名單
router.beforeEach((to, from, next) => {
  NProgress.start();
  if (whiteList.indexOf(to.path) !== -1) {
    next();
  } else {
    if (getToken()==="true") {
      next();
      NProgress.done()
    } else {
      next({path: '/login'});
      NProgress.done()
    }
  }
})

router.afterEach(() => {
  NProgress.done() // 結束Progress
})
6、utils裡的request.js裡寫攔截碼,對後端返回的特定碼進行攔截然後做相應的操作

import axios from 'axios'
import { Message, MessageBox } from 'element-ui'
import store from '../store'


// 建立axios例項
const service = axios.create({
  baseURL: process.env.BASE_API, // api的base_url
  timeout: 15000                  // 請求超時時間
});
// respone攔截器
service.interceptors.response.use(
  response => {
  /**
  * code為非200是拋錯 可結合自己業務進行修改
  */
    const res = response.data;
    //const res = response;
    if (res.code !== '200' && res.code !== 200) {
      if (res.code === '4001' || res.code === 4001) {
        MessageBox.confirm('使用者名稱或密碼錯誤,請重新登入', '重新登入', {
          confirmButtonText: '重新登入',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          store.dispatch('FedLogOut').then(() => {
             location.reload()// 為了重新例項化vue-router物件 避免bug
          })
        })
      }
      if (res.code === '4009' || res.code === 4009) {
        MessageBox.confirm('該使用者名稱已存在,請重新註冊!', '重新註冊', {
          confirmButtonText: '重新註冊',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          store.dispatch('FedLogOut').then(() => {
            location.reload()// 為了重新例項化vue-router物件 避免bug
          })
        })
      }
      return Promise.reject('error')
    } else {
      return response.data
    }
  },
  error => {
    Message({
      message: error.message,
      type: 'error',
      duration: 5 * 1000
    });
    return Promise.reject(error)
  }
)

export default service
以上就是登入註冊的核心部分,寫的不對的地方請指教