vue登录权限总结

在h5和后台开发中,我们经常需要权限登录。所以需要总结日常经常需要的几种方式。

1、路由方面

一般由vue-router和vuex完成路由体系,h5一般通过router.beforeEach()进行拦截,后台一般通过addRoutes添加路由实现菜单控制。

1.1router.beforeEach() 判断mate标识页面是否需要登录和store用户登录的标识。

//路由配置meta信息
const routes = [
  {
    path: '/',
    name: 'Home',
    component: (resolve) => require(['@/views/Home.vue'], resolve),
  }, 
  {
    path: '/login',
    component: (resolve) => require(['@/views/Login.vue'], resolve),
    name: 'Login',
    meta: {
      redirectAlreadyLogin: true //登录后,不需要再进来
    }
  },
   {
    path: '/profile',
    component: (resolve) => require(['@/views/Profile.vue'], resolve),
    name: 'Profile',
    meta: {
      requiredLogin: true //需要登录
    }
  }
]

// 路由钩子进行拦截判断是否需要登录
router.beforeEach((to, from, next) => {
  if (to.meta.requiredLogin && !store.state.use.isLogin) {
    next({ name: 'Login'})
  } else if (to.meta.redirectAlreadyLogin && store.state.user.isLogin) {
    next('/');
  } else {
    next();
  }
})

// store配置用户信息是否登录
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    user: {
      name: '张三',
      isLogin: false
    }
  }
})

export default store

1.2动态路由

简单的角色配置:只涉及管理员和普通用户的权限。通常在前端进行角色判断

复杂的路由权限:后端返回路由列表,前端渲染使用

通常不同的用户对应不同的菜单,根据用户的角色后台返回不同的路由列表,进行添加。

每一个页面动态配置权限,之后将这份路由表存储到后端。当用户登录后得到 roles,前端根据roles 去向后端请求可访问的路由表,从而动态生成可访问页面,之后就是 router.addRoutes 动态挂载到 router 上。

第一步:将公用的页面constantRouterMap放在vue-router上。

import Vue from 'vue'
import Router from 'vue-router'


Vue.use(Router)


const constantRouterMap = [
  {
    path: '/',
    name: 'Home',
    component: (resolve) => require(['@/views/Home.vue'], resolve),
  }, 
  {
    path: '/login',
    component: (resolve) => require(['@/views/Login.vue'], resolve),
    name: 'Login',
  },
  {
    path: '/profile',
    component: (resolve) => require(['@/views/Profile.vue'], resolve),
    name: 'Profile',
  },

]



export default new Router({
  mode: 'history',
  constantRouterMap
})


//动态需要根据权限加载的路由表 
export const asyncRouterMap = [
  {
    path: '/permission',
    component: Layout,
    name: '权限测试',
    meta: { role: ['admin','super_editor'] }, //页面需要的权限
    children: [
    { 
      path: 'index',
      component: Permission,
      name: '权限测试页',
      meta: { role: ['admin','super_editor'] }  //页面需要的权限
    }]
  },
  { path: '*', redirect: '/404', hidden: true }
];

第二步:当用户登录后,获取用户role,将role和路由表权限做比较,生成用户的访问的用户表。

router.beforeEach((to, from, next) => {
  if (store.getters.token) { // 判断是否有token
    if (to.path === '/login') {
      next({ path: '/' });
    } else {
      if (store.getters.roles.length === 0) { // 判断当前用户是否已拉取完user_info信息
        store.dispatch('GetInfo').then(res => { // 拉取info
          const roles = res.data.role;
          store.dispatch('GenerateRoutes', { roles }).then(() => { // 生成可访问的路由表
            router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表
            next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 
          })
        }).catch(err => {
          console.log(err);
        });
      } else {
        next()
      }
    }
  } else {
    next('/login'); 
  }
});

第三步:实现匹配路由

// store/permission.js
import { asyncRouterMap, constantRouterMap } from 'src/router';

function hasPermission(roles, route) {
  if (route.meta && route.meta.role) {
    return roles.some(role => route.meta.role.indexOf(role) >= 0)
  } else {
    return true
  }
}

const permission = {
  state: {
    routers: constantRouterMap,
    addRouters: []
  },
  mutations: {
    SET_ROUTERS: (state, routers) => {
      state.addRouters = routers;
      state.routers = constantRouterMap.concat(routers);
    }
  },
  actions: {
    GenerateRoutes({ commit }, data) {
      return new Promise(resolve => {
        const { roles } = data;
        const accessedRouters = asyncRouterMap.filter(v => {
          if (roles.indexOf('admin') >= 0) return true;
          if (hasPermission(roles, v)) {
            if (v.children && v.children.length > 0) {
              v.children = v.children.filter(child => {
                if (hasPermission(roles, child)) {
                  return child
                }
                return false;
              });
              return v
            } else {
              return v
            }
          }
          return false;
        });
        commit('SET_ROUTERS', accessedRouters);
        resolve();
      })
    }
  }
};

export default permission;

2、指令方面

import store form '@/store'

export default {
  inserted(el, binding, vnode) {
    const { value } = binding //获取v-auth=['admin']中的admin这个值
    const roles = store.getters &&  store.getters.roles

    if (value && value instanceof Array && value.length > 0 ) {
      const permissionRoles = value

      const hasPremission = roles.some(role =>{
        return permissionRoles.includes(role)
      })

      // 如果没有权限,移除当前节点
      if (!hasPremission) {
        el.parentNode && el.parentNode.removeChild(el)
      }
    } else {
      throw new Error('need roles!')
    }
  }
}

3、接口方面

一般我们用axios的拦截器(service.interceptors.request.use)header添加token,后台进行验证。根据后台返回的code做不同的判断。

// 响应拦截 对响应消息作初步的处理
service.interceptors.response.use(resp => {
  if (resp.data) {
    if (resp.data.errcode !== 0 && resp.data.errcode !== 401) {
      Notify({ type: 'danger', message: resp.data.errmsg })
    }
    return resp.data
  } else {
    Notify({ type: 'danger', message: resp.errmsg })
    return resp
  }
}, error => {

  if (error.response) {
    Notify({ type: 'danger', message: '抱歉,系统发生错误!' })
  }
})

后台权限验证参考花裤衩大佬,地址:https://juejin.cn/post/6844903478880370701

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值