我们是袋鼠云数据栈UED团队,致力于打造优秀的一站式数据中心产品。我们始终保持工匠精神,探索前端道路,为社区积累和传播经验价值。前言访问控制(Accesscontrol)是指访问者对受保护资源的访问操作的控制和管理。控制管理确保授权的人可以访问受保护的资源,而未授权的人不能访问受保护的资源。现实生活中的访问控制可以通过支付或者认证来实现。例如:去电影院看电影,需要买电影票,否则验票员是不会让你进去的。门禁控制的模型有很多,比如:全权访问控制模型(DiscretionaryAccessControl)强制访问控制模型(MAC:MandatoryAccessControl)角色访问控制模型(RBAC:Role-basedAccessControl)属性访问控制模型(ABAC:Attribute-BasedAccessControl)DAC自主访问控制(DAC:DiscretionaryAccessControl),系统会识别用户,然后根据访问对象的访问控制列表(ACL:AccessControlList)或访问控制矩阵(ACL:AccessControlMatrix)信息来确定用户可以对其进行哪些操作,比如读或调整。拥有对象权限的用户可以将对象权限分配给其他用户,因此称为“全权委托”控制。自主访问控制模型是一种相对宽松但有效的保护资源不被非法访问和使用的手段。说松是因为它是自主控制的,在保护资源的时候是以个人意志为转移的;之所以说有效,是因为它能清楚明确地指出主体是在访问还是在使用客体。实现什么样的权限,任何超出指定权限的访问行为,经过访问控制列表的判断,都会被阻止。一个比较典型的场景是在Linux文件系统中:系统中的每一个文件(有些特殊文件可能没有,比如块设备文件等)都有一个所有者。文件的所有者是创建该文件的计算机的用户(或事件,或另一个文件)。那么这个文件的自主访问控制权限就由它的创建者如何设置和分配来决定了。文件的拥有者拥有访问权限,可以为自己和其他用户分配访问权限只有那些用户(或其他主体)和文件(或其他对象)在标记的访问控制下被标记为固定的安全属性(如安全级别、访问权限等)。每次访问发生时,系统检查安全属性以确定用户是否具有访问该文件的权限。MAC最早主要用于军事应用,通常与DAC结合使用。将两种访问控制机制的过滤结果累加起来,以达到更好的访问控制效果。也就是说,只有通过了DAC限制检查和MAC限制检查双重过滤装置,主体才能真正访问客体。一方面,用户可以使用DAC来防止其他用户攻击那些属于自己的对象;另一方面,由于用户不能直接更改MAC属性,MAC提供了一个不可逾越的更强大的安全保护层,以防止其他用户无意或有意地滥用DAC。RBAC角色访问控制(RBAC:Role-basedAccessControl),各种权限不是直接授予具体的用户,而是在用户集和权限集之间建立一个角色集。每个角色对应一组相应的权限。一旦为用户分配了合适的角色,该用户就拥有该角色的所有操作权限。目前基于角色的访问控制模型被广泛应用,尤其是在2B方向的SAAS领域。这就是我们今天要关注的。RBAC虽然简化了权限的管理,但是对于复杂场景下的角色管理仍然不够灵活。例如,主体与客体之间的权限复杂多变,可能需要维护大量的角色及其授权关系;新对象还需要处理所有相关角色。基于属性的角色访问控制就是为了解决这个问题而设计的。ABAC属性访问控制(Attributes-basedAccessControl)是一种非常灵活的访问控制模型。属性包括请求体的属性、请求对象的属性、请求上下文的属性、操作的属性等。比如老张是班主任(主体的属性),上课的时候可以踢(操作的属性)普通学生的小明(客体的属性)(上下文的属性)。可见,只要对属性进行精确的定义和划分,ABAC就可以实现非常复杂的权限控制。例如:大二(年级)会计(专业)二班(班)班长(职务)可以在校内网(环境)上传(操作)班级照片。但是由于ABAC的复杂性,对于现在的SAAS领域来说有点大材小用。因此,在SAAS领域很少见到使用ABAC的平台。目前一些云服务使用ABAC较多。数据栈中的RBAC我们产品使用的是RBAC权限方案,所以目前只分析RBAC。RBAC是角色访问控制,所以我们首先要知道的是用户的角色。对此,我们的项目中有用户管理和角色管理两个模块。用户管理在登录入口的用户管理中提供创建、编辑、删除用户账号等功能。在Datastack产品中,有租户的概念,每个租户都有自己的用户管理来管理租户内的用户。能够设置当前用户的角色,包括租户所有者、项目所有者、项目经理等。角色管理在角色管理中,您可以看到角色的定义及其拥有的访问权限。通过用户管理和角色管理中的用户定义,我们可以获得当前用户完整的产品访问权限。当用户进入某个功能时,我们可以通过对比当前的访问权限和用户的访问权限,进而得出准入的结论。对于我们前端开发人员来说,我们需要的其实是用户的特定角色权限,通过用户的特定角色权限来验证权限。我们来看看antdesignpro的权限方案是怎么处理的。antdesignpro中的权限方案,业界比较常见的antdesignpro中的权限方案是如何设计的?在获取用户角色权限之初,进入页面时会进行登录验证。如果没有登录,会跳转到登录页面,进行登录操作。登录成功后,会通过setAuthority方法将当前用户的角色数据保存到localStorage中,方便我们重新进入页面时获取。通过登录验证的,直接进入项目渲染页面基本布局的BasicLayout组件。在BasicLayout组件中,我们使用Authorized组件。Authorized挂载时,会触发renderAuthorize给CURRENT赋值。后面的权限验证会用到CURRENT,这个比较关键。下面是这两种情况下方法调用的流程图:renderAuthorize方法是柯里化函数,在内部使用getAuthority获取角色数据时,为CURRENT赋值。让当前:字符串|string[]='NULL';类型CurrentAuthorityType=string|字符串[]|(()=>typeofCURRENT);/***使用权限或getAuthority*@param{string|()=>String}currentAuthority*/constrenderAuthorize=(Authorized:any)=>(currentAuthority:CurrentAuthorityType)=>{if(currentAuthority){if(typeofcurrentAuthority==='function'){CURRENT=currentAuthority();}if(Object.prototype.toString.call(currentAuthority)==='[objectString]'||Array.isArray(currentAuthority)){CURRENT=currentAuthorityasstring[];}}else{CURRENT='NULL';}returnAuthorized;};export{CURRENT};exportdefault(Authorized:any)=>renderAuthorize(Authorized);至此,项目的权限获取和更新完成。下一步是验证权限。权限验证需要以下环境参数:authority:当前访问权限为访问权限currentAuthority:当前用户的角色,即CURRENTtarget:验证成功后显示的组件Exception:验证失败的组件verified与Authorizedcomponents结合用于需要权限验证的组件。Authorized组件内部,实现了checkPermissions方法,验证当前用户角色是否有访问权限。如果有权限,则直接显示当前组件,如果没有,则显示无权限等信息。授权组件的实际情况,typeIAuthorizedType=React.FunctionComponent
