美文网首页工具集vue
Vue后台管理系统用户认证封装

Vue后台管理系统用户认证封装

作者: Evtion | 来源:发表于2019-06-11 21:30 被阅读169次

    在使用vue技术栈开发各类管理系统时,经常需要相同的开发目录架设。在日常开发中,整理了一套自己的开发目录。主要包括vuejsvue-routervuexaxios等常用类库。

    开发依赖

     "vuex": "^3.1.0",
     "babel-polyfill": "^6.26.0",
     "element-ui": "^2.9.1",
     "vue": "^2.5.2",
     "vue-router": "^3.0.1",
     "axios": "^0.18.0",
    

    Git仓库地址

    vue-template

    开发目录

    vue-template主要使用axios做请求处理,在src/api/index.js中对axios做了二次封装,然后把封装函数gl_ajax挂载在全局vue.prototype上,通过各层嵌套组件通过原型可以获取gl_ajax函数。在router/index.js主要是路由定义和路由导航守卫功能。详细情况可以参考提供源码地址。

    |-- App.vue(挂载根组件)
    |-- api(封装请求相关模块)
    |   |-- api.js(公用api接口定义)
    |   |-- config.js(项目请求地址和其他参数)
    |   |-- index.js(axios二次封装定义)
    |-- components(公用业务组件)
    |-- main.js(程序执行入口)
    |-- plugins(开发vue插件目录)
    |   |-- el_icon(Icon组件)
    |   |   |-- Icon.vue
    |   |   |-- assets
    |   |   |   |-- error.svg
    |   |   |   |-- info.svg
    |   |   |   |-- success.svg
    |   |   |   |-- warning.svg
    |   |   |-- index.js
    |   |-- el_message(message提示组件)
    |       |-- index.js
    |       |-- main.js
    |       |-- message.vue
    |-- router(路由定义和路由守卫)
    |   |-- index.js
    |-- store(vuex定义和action)
    |   |-- index.js
    |   |-- types.js
    |-- views(业务组件)
        |-- Home.vue
        |-- Login.vue
        |-- index.vue
    

    main入口

    main入口对类库进行挂载,二次封装的函数gl_ajax、第三方组件库elementuivue官方提议对挂载在vue原型链上的自定义函数加前缀$区分,这里使用alias:$gl_ajax来进行挂载。

    import Vue from "vue";
    import "babel-polyfill";
    import App from "./App";
    import router from "./router";
    import store from "./store/index.js";
    import { gl_ajax } from "./api/index.js";
    import ElementUI from "element-ui";
    import "element-ui/lib/theme-chalk/index.css";
    Vue.prototype.$gl_ajax = gl_ajax;
    Vue.config.productionTip = false;
    Vue.use(ElementUI);
    new Vue({
      el: "#app",
      store,
      router,
      components: { App },
      template: "<App/>"
    });
    

    路由定义和路由守卫

    开发后台管理系统,某些页面需要对用户或游客进行权限验证。所以在路由文件添加路由守卫,阻止未登录用户对需权限的页面的操作。

    在使用vue中采取前后端分离的形式,通过JWT获取对api接口的请求权限token,在登录中获取token,然后保存在sessionStorage中,之所以不把token保存在vuex中,是因为浏览器刷新会导致store数据重置。失去登录token。这里采用的是sessionStoragevuex的形式,避免了上述的弊端。

    // 页面刷新时,重新赋值token
    if (window.sessionStorage.getItem("token")) {
      store.commit(types.LOGIN, window.sessionStorage.getItem("token"));
    }
    

    下面是router/index.js的完整定义源码

    import Vue from "vue";
    import VueRouter from "vue-router";
    import store from "../store/index";
    import * as types from "../store/types";
    Vue.use(VueRouter);
    const routes = [{
        path: '',
        redirect: '/login'
      }, {
        path: "/",
        component: resolve => require(["@/views/Home"], resolve),
        children: [{
          path: '/admin',
          name: 'admin',
          component: resolve => require(["@/views/index"], resolve)
        }]
      },
      {
        path: "/login",
        name: "Login",
        component: resolve => require(["@/views/Login"], resolve)
      }
    ];
    
    // 页面刷新时,重新赋值token
    if (window.sessionStorage.getItem("token")) {
      store.commit(types.LOGIN, window.sessionStorage.getItem("token"));
    }
    
    const router = new VueRouter({
      mode: "history",
      routes
    });
    
    //路由导航守卫
    router.beforeEach((to, from, next) => {
      if (to.path == "/login") {
        store.commit(types.LOGOUT);
        next();
      } else {
        const token = sessionStorage.getItem("token");
        if (!token) {
          next({
            path: "/login",
            query: {
              redirect: to.fullPath
            }
          });
        } else {
          next();
        }
      }
    });
    export default router;
    

    全局数据储存vuex

    在路由导航中,使用storesessionStorage形式保存登录token,在store/index.js中也定义了登录和退出操作mutations

    把退出操作定义在store中,是为了下面对登录权限过期,返回401状态码,进行重定向操作功能。

    import Vue from "vue";
    import Vuex from "vuex";
    import * as types from "./types";
    Vue.use(Vuex);
    export default new Vuex.Store({
      state: {
        token: null
      },
      mutations: {
        [types.LOGOUT]: (state, data) => {
          sessionStorage.removeItem("token");
          state.token = null;
        },
        [types.LOGIN]: (state, data) => {
          sessionStorage.setItem("token", data);
          state.token = data;
        }
      },
      actions: {},
      getters: {}
    });
    

    axios封装

    api/index.js文件中对axios进行了二次封装。同一根目录下config.js定义请求超时时间、开发和线上请求URL

    axios请求拦截

    axios请求错误拦截是重点部分。主要对权限过期401和请求超时操作store对保存的token清除,然后再对路由进行重定向。

    axios.interceptors.response.use(
      response => {
        return response;
      },
      error => {
        if (error.response) {
          switch (error.response.status) {
            case 401:
              store.commit(types.LOGOUT);
              router.replace({
                path: "/login",
                query: {
                  redirect: router.currentRoute.path
                }
              });
          }
          const message = error.response.data.message ?:'未知错误';
          Message.error(message);
        } else if (error.code == 'ECONNABORTED' && error.message.indexOf('timeout') != -1) {
          Message.error("请求已超时");
        }
        return Promise.reject(error);
      }
    );
    
    gl_ajax请求封装

    responseTypeaxios请求文件下载需要的接受类型,文件是通过application/json方式进行获取。

    export const gl_ajax = params => {
      return axios({
          method: params.method.toLowerCase(),
          url: `${axios.defaults.baseURL}${params.url}`,
          data: params.method != "get" ? params.data : "",
          params: params.method == "get" ? params.data : "",
          responseType: params.file ? "blob" : ""
        })
        .then(res => {
          params.success && params.success(res);
        })
        .catch(err => {
          params.error && params.error(err);
        });
    };
    

    gl_ajax使用

    vue的原型上定义了$gl_ajax函数,在login常见登录中需要请求接口获取token权限,下面对$gl_ajax介绍使用方式和对token保存操作。

    self.$store.commit(types.LOGIN,token)vuex中保存token,会在sessionStoragestore分别保存一份token值。防止浏览器刷新造成vuextoken丢失。

    <template>
        <div>
            <button @click='loginSystem'>login</button>
        </div>
    </template>
    <script>
    import * as types from "../store/types.js";
    export default {
      name: "Login",
      data() {
        return {};
      },
      methods: {
        loginSystem() {
          const self = this;
          this.$gl_ajax({
            url: "/login",
            method: "post",
            data: { ...self.loginData },
            success(res) {
              if (res.data.status == "ok") {
                const token = res.data.jwt;
                self.$store.commit(types.LOGIN, token);
                self.message("login success");
                self.$router.push({
                  path: "/admin"
                });
              }
            },
            error(err) {}
          });
        }
      }
    };
    </script>
    <style>
    </style>
    

    如果觉得有帮助,可以给个赞或star

    github地址:vue-template

    相关文章

      网友评论

        本文标题:Vue后台管理系统用户认证封装

        本文链接:https://www.haomeiwen.com/subject/tmgcfctx.html