这是大冰块2021年第5篇原创文章,和大冰块一块儿在前端领域努力吧!!!💪前端
还记得在我入门没多久的时候,第一次接触公司中大型项目的时候,项目权限这块把我搞的很懵。大概是个人逻辑思惟不够强大,猛然接触新的思惟方式总是转不过弯来。不过功夫不负有心人,靠着前辈的指导和本身一点点摸索,总算对权限的总体流程(前端方面)有了一个基本的掌握。后端
现在回首再看,前端方面的权限管理其实没什么难度,就像一把钥匙开一把锁,只要把一一对应的逻辑关系作好就能够了。由于思路是类似的,因此实现的代码都是大同小异,所以本文主要以文字和逻辑图为主。数组
今天就来谈一下 项目权限 这一块,尽可能谈的简单一些,让前端小白都能明白,同时也详细说下 权限管理禁止容许 的思路,欢迎你们一块儿讨论更好的方法,也但愿抛砖引玉,能有大神来指出不足与更好的改进方法。😜缓存
简单来讲,就是不一样的用户具备不一样的权限:服务器
用户A进入页面,页面内有
增长
,查找
两个选项,markdown用户B进入页面,页面内有
增长
,查找
,修改
,删除
四个选项,网络用户C进入页面,页面提示
权限不足,3秒后将跳转首页
异步
那么若是咱们有100个用户,难不成要给他们搞100套权限吗???post
固然不是,用户并不直接对应权限,用户对应的实际上是角色 。学习
也就是说:用户对应角色,角色对应权限。若是咱们有一百个用户,可是他们等级不一样,老板有所有的权限,经理有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个功能权限添加到功能权限表中,再给角色分配对应权限便可。
这种公共的权限管理,每一个项目根据不一样的需求都有本身的处理方式。另外,权限管理也能够作成公共的组件,新建项目时引入配置便可,此处暂不作讨论了。
这是大冰块《看完就懂系列》的第4篇文章,《看完就懂系列》旨在把一些常见的概念或方法以通俗易懂的方式呈现出来。欢迎你们点击其余文章一块儿讨论学习:
原创不易,若有错误,欢迎指出。
若是有帮助到你,请给大冰块来个三连(点赞收藏评论),让咱们一块儿在前端的路上进步吧~🤭