写点什么

《看完就懂系列》项目中的权限管理复杂吗?

  • 2022 年 7 月 09 日
  • 本文字数:2601 字

    阅读完需:约 9 分钟

写在前面


还记得在我入门没多久的时候,第一次接触公司中大型项目的时候,项目权限这块把我搞的很懵。大概是我的逻辑思维不够强大,猛然接触新的思维方式老是转不过弯来。不过功夫不负有心人,靠着前辈的指导和自己一点点摸索,总算对权限的整体流程(前端方面)有了一个基本的掌握。

如今回首再看,前端方面的权限管理其实没什么难度,就像一把钥匙开一把锁,只要把一一对应的逻辑关系做好就可以了。因为思路是相似的,所以实现的代码都是大同小异,因此本文主要以文字和逻辑图为主。

今天就来谈一下 项目权限 这一块,尽量谈的简单一些,让前端小白都能明白,同时也详细说下 权限管理禁止允许 的思路,欢迎大家一起讨论更好的方法,也希望抛砖引玉,能有大神来指出不足与更好的改进方法。😜

什么是权限管理

简单来说,就是不同的用户具有不同的权限:


用户 A 进入页面,页面内有增加查找两个选项,

用户 B 进入页面,页面内有增加查找修改删除四个选项,

用户 C 进入页面,页面提示权限不足,3秒后将跳转首页


那么如果我们有 100 个用户,难不成要给他们搞 100 套权限吗???


当然不是,用户并不直接对应权限,用户对应的其实是角色


也就是说:用户对应角色,角色对应权限。如果我们有一百个用户,但是他们等级不同,老板有全部的权限,经理有 80%权限,组长有 50%权限,职员有 20%权限。


那么其实我们只需要 4 个角色:老板角色 有全部的权限,经理角色 有 80%权限,组长角色 有 50%权限,职员角色 20%权限。


用户只要对应这 4 个角色即可,不同级别的用户就能有不同的权限了。


值得注意的是:


用户和角色的对应可以是单对多的 ,一个用户可以有多个角色,比如用户小明是经理,但他可能临时兼职一个组长,所以他对应的角色是经理+组长

角色和权限的对应也是单对多的 ,一个角色不一定只有一个权限,这个角色可能具有全部的权限(增删改查等),也可能只有一部分权限(增删)。


上面的说明可以改成这样:


用户 A 进入页面,用户 A 对应的角色是职员,所有职员角色进入页面,页面内都会有增加查找两个选项,

用户 B 进入页面,用户 B 对应的角色是组长,所有组长角色进入页面,页面内都会页面内有增加查找修改删除四个选项,

用户 C 进入页面,用户 C 没有对应的角色,没有对应角色的用户进入页面,页面都会提示权限不足,3秒后将跳转首页

权限管理的逻辑图

文字说明可能有不到位的地方,下面我们来用流程图的形式来更直观的表现一下权限管理的逻辑。

页面权限逻辑图

在路由拦截中判断当前用户是否具有对应的页面路由权限。



★功能权限逻辑图

在页面渲染前,判断当前用户是否具有当前页面某功能的权限,决定是否渲染。

后端要对权限做二次鉴权处理,避免页面渲染错误或者缓存问题,导致功能权限显示,从而误操作。



★数据权限共享逻辑图

数据权限共享本质上是新加了一个临时角色,把临时角色加给被分享者即可。

同时,临时角色应当记录自身创建时间,过期时间,分享者 ID 以及被分享者的 ID,方便后期统计溯源。


权限管理的代码实现

代码实现一般是通过路由拦截请求拦截共同实现,因为不同的项目代码结构可能有所不同,所以如下代码只是思路的一个延展说明,并不能直接拷贝到项目中使用哦~


 // 路由拦截
// name 要前往的路由 // access 用户权限数组 // routes 路由列表 const canTurnGo = (name, access, routes) => { const routePermission = (list) => { return list.some(item => { if (item.children && item.children.length) { return routePermission(item.children) } else if (item.name === name) { return hasAccess(access, item) } }) } return routePermission(routes) } ... // 请求拦截 // 在拦截到http状态码非200时调用的方法 const errorHandler = function(error) { const codeMap = { 200: '服务器成功返回请求的数据', 201: '新建或修改数据成功', 202: '一个请求已经进入后台排队(异步任务)', 204: '删除数据成功', 400: '发出的请求有错误,服务器没有进行新建或修改数据的操作', 401: '用户没有权限(令牌、用户名、密码错误)', 403: '用户得到授权,但是访问是被禁止的', 404: '发出的请求针对的是不存在的记录,服务器没有进行操作', 406: '请求的格式不可得', 410: '请求的资源被永久删除,且不会再得到的', 422: '当创建一个对象时,发生一个验证错误', 429: '请求次数超出当天上限', 500: '服务器发生错误,请检查服务器', 502: '网关错误', 503: '服务不可用,服务器暂时过载或维护', 504: '网关超时', } const {response} = error if (response) { // 获取http状态码对应的错误信息 const errorText = codeMap[response.status] || response.statusText // 如果某个状态码要执行特殊操作,则: if(status === 403){ throw new Error(errorText) }else{ throw new Error(errorText) } } else { notification.error({ description: '您的网络发生异常,无法连接服务器', message: '网络异常', }) } return}
复制代码

总结

类似于这种权限管理,最重要的还是考虑问题的思路,有了正确的思路转化为代码就很容易了。


按照权限-角色-用户的管理方式,后期权限的维护以及增删改查都可以放在前端来处理,后端只要配置一次就可以不再操作了。避免了后端代码在权限管理的逻辑杂乱,不好维护等问题。简单来说,每个权限都有一个唯一的 id,用户登录后去判断用户对应的角色是否对应有某权限的 id,作为判断用户是否具有某权限的标准。如果新增一个页面,里面有 n 个功能权限,只需把路由地址以及加入到路由权限表中,把 n 个功能权限添加到功能权限表中,再给角色分配对应权限即可。


这种公共的权限管理,每个项目根据不同的需求都有自己的处理方式。另外,权限管理也可以做成公共的组件,新建项目时引入配置即可,此处暂不做讨论了。

写在后面

这是大冰块《看完就懂系列》的文章,《看完就懂系列》旨在把一些常见的概念或方法以通俗易懂的方式呈现出来。




原创不易,如有错误,欢迎指出。

如果有帮助到你,请给大冰块来个三连(点赞收藏评论),让我们一起在前端的路上进步吧~🤭


发布于: 刚刚阅读数: 3
用户头像

还未添加个人签名 2022.07.01 加入

还未添加个人简介

评论

发布
暂无评论
《看完就懂系列》项目中的权限管理复杂吗?_7月月更_南极一块修炼千年的大冰块_InfoQ写作社区