阅读 505

基于导航守卫实现页面的权限控制

前言

作为一个前端开发,我们有时候会遇到一些没有权限访问的页面,或者通过点击某个按钮但却没有权限。鉴于自己遇到了这样的问题,所以在这里做一个总结

需求分析

系统管理员能够进入角色页面,并且通过功能权限或者页面权限给用户分配权限,包括用户是否有权限访问某个页面,或者是通过编辑以及添加这种操作进入某个页面,如下图所示。

可以看到第二张图,我们给这个角色为测试的用户,对某个页面的功能进行了权限设置,点击确定后,角色为测试的用户将无法使用该页面的编辑以及新增功能。

到这里还不算真正的达到了权限控制,这里我们只是通过对编辑以及新增这两个功能进行了权限控制,从而阻止用户进入编辑或者新增页面。

实际上, 既然我们不能通过点击的方式进入页面,那我们能不能直接通过路由的方式直接访问呢?答案是如果我们没有做路由权限的控制,那就是可以的。

也就是说,就算我不能通过点击编辑或者新增进入页面,但只要我知道编辑或者新增的页面对应的url, 我就能够访问到这个页面。

因此我们必须从两个方面对页面进行权限控制。 因为通过点击进入页面的方式已经做了权限控制了,那么剩下的就是限制通过url来访问页面了。

第一步, 点击操作(编辑或者新增)的权限是如何控制的

这个应该根据后端接口返回的数据结构来决定, 比方说后端现在返回给我一个这样的数据结构

{
  code: 0,
  data: [{
    comment: '编辑',            // 功能名称
    checkStatus: false          // 功能权限
  }, {
    comment: '新增',
    checkStatus: true
  }]
}
复制代码

对应的编辑页面的route

routes: [{
  name: 'article-edit',
  path: '/article/edit',
  beforeEnter: (to, from, next) {
    http.get(apis.getButtonsPowerList, {
      params: {
        pageId: xxxx
      }
    }).then(res => {
      if(res.code === 0) {                                 // code为0说明请求成功
        let btnsPowerList = res.data                       // 获取按钮权限列表
        for(let i = 0; i < btnsPowerList.length; i++) {
          if(btnsPowerList[i].comment === '编辑') {        // 找到comment为编辑的按钮
            if(btnsPowerList[i].checkStatus) {             // 判断编辑按钮的checkStatus是否为true
              next()                                       // 如果为true,表示有权限,则进入相应页面
            } else {                                       // 否则提示用户没有访问权限,并且退回上一页面
              setTimeout(() => {
                window.history.go(-1)
              })
              alert('您没有访问该页面的权限')
            }
          }
        }
      }
    })
  }
}]
复制代码

从上述代码来说,功能是实现了,但是像这样的控制页面权限的功能,我们需要将其封装起来,否则会造成大量的代码冗余。所以下面是封装之后的代码。

export function isAuthRoute(comment, pageId, next) {
  new Promise(resolve => {
    _isAuth(comment, pageId, resolve)
  }).then(res => {
    if(!res) {
      setTimeout(() => {
        window.history.go(-1)
      }, 1500)
      alert('您没有访问该页面的权限')
    } else {
      next()
    }
  })
}
 
function _isAuth(comment, pageId, callback) {
  http.get(apis.getButtonsPowerList, {
    params: {
      pageId
    }
  }).then(res => {
    if(res.code === 0) {
      let btnsPowerList = res.data                      
      for(let i = 0; i < btnsPowerList.length; i++) {
        if(btnsPowerList[i].comment === comment) {       
          callback(btnsPowerList[i].checkStatus)
        }
      }
    }
  })
}
复制代码

调用的方式也很简单

routes: [{
  name: 'article-edit',
  path: '/article/edit',
  beforeEnter: (to, from, next) {
    isAuthRoute('编辑', pageId, next)
  }
}]
复制代码

注意,以上的调用接口的方式以及传参的内容,需要根据自身的需求来决定

总结

其实这部分的代码,最多只是提供了一个思路,因为不同的场景肯定写出来的代码也是不一样的。在这个需求当中,我学习到的东西更多的是一个执行顺序的问题,我们知道文中使用的 beforeEnter 会在进入页面之前调用,但是请求数据的接口是异步的, 而我们需要通过异步接口返回的数据来判断是否有权限进入页面,这意味着我们必须先拿到数据再去做判断,所以这个时候我们更希望保持一个同步的顺序,所以这里才使用了promise由于promise中的then中的回调函数必须等到resolve后才会被执行, 因此我们将resolve作为参数传递给真正调用了接口的函数直到接口返回数据之后,再在接口请求完毕的回调里面调用resolve,通过这样的方式,就能够确保在做权限判断的时候,一定能够拿到数据。

最后,如果能够帮到各位,请不要吝惜点赞哦,谢谢。

以上的内容来自于我的csdn博客,因为没啥人看,就搬过来掘金了。 我的csdn地址: blog.csdn.net/huangguangy…

关注下面的标签,发现更多相似文章
评论