vue添加权限校验

前端的权限校验可以分为菜单校验、接口和按钮的校验。

菜单权限

把接口权限和按钮权限统称为资源权限,在数据库中以字段区分,然后把菜单权限也存入数据库,然后再把登录和获取权限等接口加入白名单,当登录成功后,在路由切换中取用户权限,即菜单和资源,菜单数据转换格式存入 store 然后再生成菜单。

这样本地就无需再声明一堆路由,直接从数据库读取。更加方便快捷。

接口权限校验

登录后去调取用户的菜单权限和资源权限,然后把菜单权限动态添加为路由,资源权限转换格式存入 store,然后把登录和调用用户权限的接口加入白名单,再在 axios 的拦截器中添加拦截校验,从 store 中取出存储好的资源权限,与当前访问的接口地址进行对比,如对比结果为 true 则表示可以访问,否则提示没有权限跳转到 401 页面。

按钮权限校验

网上大部分教程都是通过挂在一个检测函数,然后在按钮上通过这个函数来处理按钮的显示与隐藏。

定义好对比函数后,在按钮上调用函数,传入资源权限的 title 来与本地存储的权限列表进行对比,有则显示,无则隐藏。

具体实现

路由切换和检测,异步获取路由拼装右侧菜单和资源权限。


const _import = require('@/router/_import')
let routers

router.beforeEach((to, form, next) => {
  Nprogress.start()
  if (get('token')) {
    if (setter.whiteList.indexOf(to.path) !== -1) {
      to.path === '/login' ? next({ path: '/' }) : next()
      NProgress.done()
    } else {
      !routers
        ? !store.getters.addRouters.length || store.getters.addRouters.length === 0
          ? getAsyncRouter(to, next)
          : routerGo(to, next, store.getters.permission_routers)
        : (next(), Nprogress.done())
    }
  } else {
    /* 白名单校验 */
    setter.whiteList.indexOf(to.path) !== -1 ? next() : next(`/login?redirect=${to.path}`)
    Nprogress.done()
  }
})

function routerGo(to, next, data) {
  routers = filterAsyncRouter(data)
  store.dispatch('GenerateRoutes', { routers }).then(() => {
    // 404只能放在异步路由,否则造成刷新404
    routers.push({ path: '*', redirect: '/404', hidden: true })
    router.addRoutes(routers)
    next({ ...to, replace: true })
    Nprogress.done()
  })
}

// 遍历后台传来的路由字符串,转换为组件对象
function filterAsyncRouter(asyncRouterMap) {
  const accessedRouters = asyncRouterMap.filter(route => {
    if (route.component) route.component = route.component === 'Layout' ? Layout : _import(route.component)
    if (route.children && route.children.length) route.children = filterAsyncRouter(route.children)
    return true
  })
  return accessedRouters
}

function getAsyncRouter(to, next) {
  getPermissions().then(response => {
    routerGo(to, next, response.data.menus)
    saveElement(response.data.elements)
  }).catch((error) => {
    console.log(error)
  })
}

/**
 * 转换资源格式并存储
 * @param elements
 */
// todo 优化
function saveElement(elements) {
  const requests = {}; const buttons = {}; const localHash = { requests, buttons }
  elements.forEach(item => {
    requests[item.method.toLowerCase() + ',' + item.path] = true
    buttons[item.title] = true
  })
  store.dispatch('GenerateElementss', { localHash })
}

import

module.exports = file => require('@/views/' + file + '.vue').default

接口校验


service.interceptors.request.use(
  config => {
    const localElement = store.getters.elements
    const url = config.url.replace(/[0-9]/ig, '*').replace(/\*+/g, '*')

    store.getters.token && (config.headers[setter.tokenName] = get('token'))
    const data = {
      ...(config.method === 'get' || config.method === 'GET' ? (config.params || {}) : (config.data || {})),
      sequenceId: uuid().replace(/-/g, ''),
      timestamp: new Date().getTime()
    }
    const sign = common.getSign(setter.apiKey, data)
    config.method === 'get' || config.method === 'GET' ? (config.params = {
      ...(data || {}),
      sign: md5(sign)
    }) : (config.data = {
      ...(data || {}),
      sign: md5(sign)
    })
    return setter.httpWhiteList.indexOf(url) === -1
      ? (localElement.requests && !localElement.requests[config.method + ',' + url])
        ? (router.push({ name: '401' }), Promise.reject('没有访问权限')) : config
      : config
  },
  error => {
    if (setter.debug) {
      console.log(error)
    }
    Promise.reject(error.message)
  }
)

资源校验

在需要校验权限的按钮上添加 v-has="'posts_add'" 即可


Vue.directive('has', {
  bind: function(el, binding, vnode) {
    (!Vue.prototype.$_has(binding.value)) && el.parentNode.removeChild(el)
  }
})

Vue.prototype.$_has = function(value) {
  const elements = store.getters.elements
  if (!elements || !elements.buttons) return false
  if (elements.buttons[value]) return true
  return false
}

具体的实现大概就是如此了,菜单和资源的格式以及获取后在本地的存储都可以根据自己实际情况来处理,没必要照搬。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,251评论 4 61
  • 游戏回顾:不复盘累述过程,游戏中不在以最终出圈为目的,只想通过游戏过程论证自己的投资体系的构建,本次出圈完成率26...
    是的陛下阅读 175评论 0 0
  • 王煜全 北美风力发电造成每年20万到30万只的鸟儿死亡,我们当然要辩证地看这个数字,美国的家猫每年就会杀死上10亿...
    alucardzhou阅读 330评论 0 0
  • 昨天下午我约雪儿见面,因为最近我在潇洒姐王潇的趁早公众号里看见了她,她入选了趁早2017年SHAPEGIRL...
    30Plus女子阅读 661评论 9 7
  • 突然有点受伤。木事,老妈说,别急哈,你值得拥有更好的,静静的等待,一切都会到来的。
    妃妃子笑阅读 312评论 0 0