有小伙伴说微人(https://github.com/lenve/vhr)的权限粒度不够细。但宋歌想说的是,技术都是相通的。了解了vhr中权限管理的原理后,在此基础上,可以细化权限管理的粒度。vhr中使用的精炼过程和技术仍然沿用。这只是设计层面的重新设计。当然,我今天要说的不是这个话题。主要想和大家聊聊SpringSecurity中权限管理的粒度。因为这个问题会涉及到不同的权限管理模型,今天和小伙伴们聊一聊~1.权限管理模型为了细化权限粒度,我们不可避免的会涉及到一些权限模型,比如ACL、RBAC、DAC、MAC和ABAC,PBAC等。在这众多的权限模型中,RBAC是我们用的最多的,ACL的一些项目也用到了,其他的相对来说用的比较少。所以宋哥在这里重点给大家介绍一下ACL和RBAC。1.1ACLACLACL是一个比较老的权限控制模型。英文全称AccessControlList,中文称为访问控制列表。这是一种面向资源的访问控制模型,所有的权限配置都是针对资源的。其原理是:对于系统中的每一个资源,都会配置一个访问列表,记录用户/角色对该资源的CURD权限。当系统需要访问这些资源时,会先检查列表中是否有当前资源。用户的访问权限,进而判断当前用户是否可以进行相应的操作。ACL的使用非常简单,了解其原理,分分钟就能实现。但是ACL有一个明显的缺点,就是需要维护大量的访问权限列表。大量访问控制列表带来的问题是性能下降和维护复杂。1.2RBACRBAC(Role-basedaccesscontrol)是一种基于角色的访问控制,也是目前应用比较广泛的一种权限模型。它有许多不同的变体。宋兄稍后会写一篇文章。介绍RBAC,这里只是简单的科普一下。RBAC权限模型按照角色对用户进行分类,通过用户的角色来判断用户是否具有对某个资源的操作权限。RBAC简化了用户和权限的管理。它将用户与角色、角色和权限以及权限与资源相关联。这种模式使得用户权限管理非常简单,易于维护。1.3其他下面的用途比较少见,朋友们可以稍微研究一下,有兴趣的朋友也可以自己研究一下。ABAC:这是一种基于属性的访问控制。PBAC:这是一种基于策略的访问控制。DAC:除了权限控制,主体还可以给其他主体授予权限。MAC:哪些类型的主体可以对资源进行哪些操作,主体可以操作哪些级别的资源。当这两个条件同时满足时,才允许访问。2.ACL接下来宋哥要给大家详细介绍一下ACL的权限模型。关于RBAC我以后会写一篇文章,本文不展开讨论。Acl的全称是AccessControlList,也就是我们所说的访问控制列表,用来控制对象的访问权限。Acl的核心思想之一就是把对某个对象的某个权限授予某个用户或某个角色。它们之间是多对多的关系,即一个用户/角色可以对一个对象拥有多个权限,对象权限也可以由多个用户/角色持有。举个简单的例子:现在有一个User对象,它对这个对象有查询、修改、删除等权限。可以将这些权限分配给某个用户,也可以将这些权限分配给某个角色。当用户拥有这些角色时就有权限执行相应的操作。从这个角度来说,Acl是一个非常细粒度的权限控制,具体控制对某个对象的操作权限。这些权限都记录在数据库中,这带来的另一个问题是需要维护的权限数据量非常大,不利于后期扩展。当然,对于一个简单的系统,使用Acl还是可以毫无问题的。2.1核心概念接下来我们来看一下Acl中的一些核心概念。SidSid代表用户和角色,它有两种类型:GrantedAuthoritySid和PrincipalSid,前者代表角色,后者代表用户。在SpringSecurity中,Authentication对象中保存了用户和角色信息,即从Authentication对象中提取Sid,提取的值为GrantedAuthoritySid+PrincipalSid,没有之一。具体提取方法为SidRetrievalStrategyImpl#getSids,相关源码如下:newArrayList<>(authorities.size+1);sids.add(newPrincipalSid(authentication));for(GrantedAuthorityauthority:authorities){sids.add(newGrantedAuthoritySid(authority));}returnsids;}这个Sid可以简单理解为当前用户的权限(这个说法不是很准确,可以大概理解)。ObjectIdentityObjectIdentity是一个域对象。这是官方的说法,有点啰嗦。其实这就是你要操作的对象。例如,我有一个用户对象。如果我直接记录可以对User对象进行哪些操作,这样会导致高耦合。因此,我们需要对其进行解耦,将所有需要操作的对象都通过ObjectIdentity来描述,从而保证权限系统不绑定到具体的服务上。ObjectIdentity中有两个关键方法,getType和getIdentifier。一般来说,getType方法返回真实对象类的全路径,比如org.javaboy.acl.model.User,getIdentifier方法返回真实对象的id。通过这两个方法,可以锁定一个对象。acl从名字就可以看出,它是整个系统的核心调度部分。一个Acl对象关联一个ObjectIdentity,一个Acl对象还有一个Sid,表示这个Acl属于谁。属于它的任何人都可以修改甚至删除Acl对象。AccessControlEntryAccessControlEntry缩写为ACE,一个AccessControlEntry对象代表一个权限记录。每个AccessControlEntry对应一个Acl,一个Acl对象对应多个AccessControlEntry。有了这个层级的对应关系,就相当于知道了权限操作的是哪个对象。那么AccessControlEntry中还包含一个Sid和一个Permission对象,表示某个Sid有一定的权限。可以看出Acl+ACE描述了某个Sid可以有某个ObjectIdentity的某个Permission。权限是具体的权限对象。好像是受Linux的影响,使用了权限掩码,最多支持232-1个权限。SpringSecurity默认定义了五种类型:publicclassBasePermissionextendsAbstractPermission{publicstaticfinalPermissionREAD=newBasePermission(1<<0,'R');//1publicstaticfinalPermissionWRITE=newBasePermission(1<<1,'W');//2publicstaticfinalPermissionCREATE=new
