Protogalaxy

Planet #0

PHSS-Core开发日志#9 Spring Security ACL配置#1

在完成了PHSS-Core对Spring Security的引入的初期阶段是之后,我又引入了Spring Data REST用来快速构建RESTful的资源访问与操纵API,在实现了Spring Data REST的基本功能之后,又有一个新的问题出现了–那就是REST API下资源的访问权限问题。

在只有Spring Security基础配置的情况下,用户登录后,通过RESTful api(/rest)可以访问到数据库中的所有资源,也就是说当某个登录后,调用/rest/musicAlbumEntities接口,不仅可以看见属于自己的专辑,还可以看见整个数据库中其他用户的专辑。经过对Spring Data REST的说明文档的一番研读,发现最接近我的要求的是@PreAuthorize功能,该注解提供了方法级的安全性控制,也就是说只有特定用户才能访问特定方法,但在经过尝试之后PreAuthorization模型并不能满足我的需求,所以我又将眼光转回到了Spring Security的说明文档上。

这时在Spring Security说明文档的末尾,我注意到了对ACL(域对象安全性)的介绍:在复杂的应用程序中,通常需要更细粒度的权限控制,而不仅仅是在Web请求或者方法调用的级别设定权限。这种情况下,安全决策需要包含who(Authentication),where(MethodInvocation),what(SomeDomainObject)三个要素。换句话说,授权决策还需要考虑到方法调用的实际域对象。

下面开始干货介绍:

Spring Security ACL大致为开发者提供了以下三种功能:

  1. 有效的检索并修改所有域对象的ACL记录
  2. 在方法被调用之前,确保当前用户拥有操纵当前对象的权限
  3. 在方法被调用之后,确保当前用户拥有操纵这些方法(或得到其返回值)的权限

为了提高检索效率,Spring Security的ACL检索功能使用了独立于ORM的JDBC查询手段。由于ACL记录都保存于数据库中,所以数据库理所应当的成为了Spring Security ACL模块的操作核心,下面以由少到多的顺序列举了Spring Security ACL部署中使用到的的四个默认主表:

  1. ACL_SID
  2. ACL_CLASS
  3. ACL_OBJECT_IDENTITY
  4. ACL_ENTITY

下面进行分别介绍:

  • ACL_SID:使我们可以唯一性的识别当前系统中的用户或者是权限。表中只有一个名为ID的列,是SID的文本形式表示,并且也可以当作识别是用户还是权限的标志。所以,每个用户或是权限都拥有唯一的SID,在接受permission时,SID一般被称为”recipient“。
  • ACL_CLASS:是我们可以唯一性的识别系统中的域模型类(domain object class),只有ID与JAVA类名两列。每个存储ACL权限的唯一类,都对应数据库中的一行。
  • ACL_OBJECT_IDENTITY:存储所有唯一域模型实例的信息,每个recipient都拥有一行,包括:
    1. ID-ACL_CLASS表外键
    2. 唯一性ID-用来识别接收信息的ACL_CLASS实例
    3. parent-用来识别域模型拥有者的ACL_SID表外键
    4. 一个用来鉴别我们是否允许ACL进行继承的标志。
  • ACL_ENTITY:存储分配给每个recipient的权限,每个接收许可的recipient都有一行,列包括:
    1. ACL_OBJECT_IDENTITY表外键
    2. recipient-即ACL_SID表外键
    3. 是否进行审计的标志
    4. integer bit形式的掩码-代表了每个特定权限是否被许可,最多可以有32位

Spring Security ACL的核心接口有以下几个:

  • Acl:每个域对象都有且仅有一个Acl对象,它们在内部拥有AccessControlEntrys并且知道该Acl的所有者。Acl不直接指向域对象,而是指向一个ObjectIdentity。Acl存储在ACL_OBJECT_IDENTITY表。
  • AccessControlEntry:Acl保存多个AccessControlEntrys,在框架中通常缩写为ACE。每个ACE引用特定的一组(tuple)Permission,Sid与Acl。ACE可以是准许或者不准许,并且其包含审计的相关设置。ACE存储在ACL_ENTRY表中。
  • Permission:一段特定的,不可变的掩码,并且提供了一组函数方便位屏蔽和输出信息。上面介绍的基本权限(0到4位)包含在BasePermission类中。
  • Sid:ACL模块需要引用principals 与GrantedAuthority[]s。Sid接口提供了一些间接层(indirection)用来表示security identity。常见的类包括PrincipalSid(即Authentication对象内的principal)和GrantedAuthoritySid。security identity信息存储在ACL_SID表中​​。
  • ObjectIdentity:每个域对象都被ACL模块在内部通过ObjectIdentity表示。默认实现为ObjectIdentityImpl。
  • AclService:检索用于给定的ObjectIdentity的Acl。在内部的(JdbcAclService)实现中,检索操作被委托给了LookupStrategy。LookupStrategy提供了一个高度优化的策略来查询ACL信息。
  • MutableAclService:对Acl的持久化进行修改。

发表评论