美文网首页业务专题
前端业务之权限管理

前端业务之权限管理

作者: Mstian | 来源:发表于2021-01-11 14:51 被阅读0次

    权限管理在前端属于绕不开的一个话题,尤其是后台管理系统类的业务,需要明确权限。最近业务上也遇到一些权限相关问题,经过查阅一些资料,记录下前端权限管理的常见场景以及方案。

    由于目前主要常见的权限问题集中在SPA单页应用中,因此这里只讨论SPA应用中的关于权限的校验。

    说前端权限之前,先说下后端权限。不管前端权限设计怎么完美,后端的权限校验都不能省,权限问题,安全问题在前端是没办法做到真正有用的,因此,后端校验必不可少,切记,切记。

    后端权限校验:

    后端权限大致思路是,用户登录之后获取一个token,每次请求时携带该token,后端根据token是否有效决定是否有资源访问权限。
    伪代码如下:

    axios.interceptors.request.use(config => {
        config.headers['token'] = cookie.get('token')
        return config
    })
    axios.interceptors.response.use(res=>{},{response}=>{
        if (response.data.code === 40099 || response.data.code === 40098) { //token过期或者错误
            router.push('/login')
        }
    })
    
    前端权限校验:

    接着到重点前端权限

    前端权限按照使用场景分为:按钮权限 路由权限 菜单权限

    按钮权限
    按钮权限相对来说比较简单,一般根据用户的角色信息(后端控制,一般通过接口返回)直接控制按钮是否渲染,或者控制按钮是否可点击即可。

    伪代码:

    <el-form>
    <!-- 表单内容 -->
    </el-form>
    
    <el-button v-if="hasRole"> 提交信息 </el-button>
    <!-- 或者disable -->
    <el-button :disabled="hasRole"> 提交信息 </el-button>
    

    小技巧:可以将hasRole直接存在vuex中调用起来比较方便。

    路由权限
    路由权限根据场景需要也分为几种看以下场景。
    场景一:路由可访问。
    场景二:路由不可访问。
    针对场景一,路由可访问就是注册好所有路由,用户登录后,访问路由的时候在路由拦截器 router.beforeEach() 里面做判断是否可访问,如果可以就继续访问,如果不可以,那就直接拦截不让其访问。
    伪代码:

    const {routeAuthList} = login() // 一般后端给出可访问路由接口
    cosnt whiteList = ['/login','/','/404'] // 不需要权限的即可访问的路由
    // 合并总路由
    whiteList = whiteList.concat(routeAuthList)
    //路由守卫判断
    router.beforeEach((to, from, next) => {
        //权限校验
        let pass = whiteList.includes(to);
        if(!pass){
            alert('无权访问')
            return;
        }
        next();
    });
    

    针对场景二,路由不可访问是指,当用户没有某个路由访问权限的时候,直接去访问该路由的时候会直接报404访问路由不存在,而不是像场景一一样提示没有权限。
    这种场景一般是这样操作的:
    首先注册不需要权限即可访问的路由,然后通过vue-router的api router.addRoutes()直接动态生成有权限的路由。

    伪代码:

    const {routeAuthList} = login() // 一般后端给出可访问路由接口
    cosnt whiteList = ['/login','/','/404'] // 不需要权限的即可访问的路由
    //路由守卫判断
    router.beforeEach((to, from, next) => {
      if(login === false) { // 判断是否已经登录(未登录时)
        store.dispatch("GETUSERINFO").then((res) => { // 获取后端返回的用户权限路由数组
          const roles = res.data.roles;
          store.dispatch("GENERATEROUTES", {roles}).then(() => { // 加工成router.addRoutes可接收的参数形式
            router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表
            next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
          })
        })
      }
    })
    

    该情况的核心就是router.addRoutes()

    菜单权限
    菜单权限实际上也是路由权限,只不过比路由复杂一点,需要同时协调menu的激活态,所以一般也是有两种场景。

    场景一:没有权限的菜单依然可见,点击菜单访问时在路由拦截器中进行拦截,阻断访问。
    场景二:没有权限的菜单直接不可见,也就无法访问。

    场景一和路由权限的场景一相同,区别就在于菜单激活问题。

    场景二

    router.beforeEach(async (to, from, next) => {
      if(login === false) { // 判断是否已经登录(未登录时)
        await store.dispatch("GETUSERINFO"); // 获取用户信息,里面包含可访问menu列表
        await store.dispatch("UPDATEMENU"); // 两个功能,1. 调用addRoutes()增加动态路由  2. 更新菜单,将菜单路由存储在vuex中。
        if (to.path === '/login') {
              next({ name: 'home_index' })
            } else {
              next({ ...to, replace: true })//菜单权限更新完成,重新进一次当前路由
            }
      }
    })
    

    这种场景核心就是需要在获取到用户的可访问menu列表后,使用addRoutes()方法动态添加路由,之后还需要更新menu。

    参考资料:
    https://mp.weixin.qq.com/s/kku7-HJ1UjOUD29fXf446Q
    https://segmentfault.com/a/1190000020887109

    相关文章

      网友评论

        本文标题:前端业务之权限管理

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