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
}

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

猜你喜欢

转载自blog.csdn.net/weixin_34419321/article/details/87473592