Spring Security(19)——对Acl的支持

本文详细介绍了Spring Security的Acl(访问控制列表)功能,包括四张核心数据库表的用途,Acl的主要接口如Sid、ObjectIdentity、Acl、AccessControlEntry等,以及如何配置AclService。重点讲解了如何创建、查找、更新和删除Acl,以及如何将AclPermissionEvaluator注入到权限控制中进行方法级别的权限校验。
摘要由CSDN通过智能技术生成


 

       Acl的全称是Access Control List,俗称访问控制列表,是用以控制对象的访问权限的。其主要思想是将某个对象的某种权限授予给某个用户,或某种GrantedAuthority(可以简单的理解为某种角色),它们之间的关系都是多对多。如果某一个对象的某一操作是受保护的,那么在对该对象进行某种操作时就需要有对应的权限。

 

1.1     准备工作

       使用Spring Security的Acl功能需要引入Acl相关的jar包。如果我们的应用是使用Maven构建的,则可以在应用的pom.xml文件中加入如下依赖。

   <dependency>

      <groupId>org.springframework.security</groupId>

      <artifactId>spring-security-acl</artifactId>

      <version>${spring.security.version}</version>

   </dependency>

 

       此外,使用Spring Security的Acl时需要在数据库中建立四张表。在其官方文档中给出了一个基于数据库HSQLDB的建表语句。其脚本如下:

create table acl_sid (

  id bigint generated by default as identity(start with 100) not null primary key,

  principal boolean not null,

  sid varchar_ignorecase(100) not null,

  constraint unique_uk_1 unique(sid,principal) );

 

create table acl_class (

  id bigint generated by default as identity(start with 100) not null primary key,

  class varchar_ignorecase(100) not null,

  constraint unique_uk_2 unique(class) );

 

create table acl_object_identity (

  id bigint generated by default as identity(start with 100) not null primary key,

  object_id_class bigint not null,

  object_id_identity bigint not null,

  parent_object bigint,

  owner_sid bigint not null,

  entries_inheriting boolean not null,

  constraint unique_uk_3 unique(object_id_class,object_id_identity),

  constraint foreign_fk_1 foreign key(parent_object)references acl_object_identity(id),

  constraint foreign_fk_2 foreign key(object_id_class)references acl_class(id),

  constraint foreign_fk_3 foreign key(owner_sid)references acl_sid(id) );

 

create table acl_entry (

  id bigint generated by default as identity(start with 100) not null primary key,

  acl_object_identity bigint not null,ace_order int not null,sid bigint not null,

  mask integer not null,granting boolean not null,audit_success boolean not null,

  audit_failure boolean not null,

  constraint unique_uk_4 unique(acl_object_identity,ace_order),

  constraint foreign_fk_4 foreign key(acl_object_identity)

      references acl_object_identity(id),

  constraint foreign_fk_5 foreign key(sid) references acl_sid(id) );

 

       笔者使用的是Oracle数据库,其中没有boolean和主键自增功能,对于boolean类型都使用一位number表示。具体建表语句如下所示:

create table acl_sid (

  id number not null primary key,

  principal number(1not null,

  sid varchar(100not null,

  constraint unique_uk_1 unique(sid,principal) );

 

create table acl_class (

  id number not null primary key,

  class varchar(100not null,

  constraint unique_uk_2 unique(class) );

 

create table acl_object_identity (

  id number not null primary key,

  object_id_class number not null,

  object_id_identity number not null,

  parent_object number,

  owner_sid number not null,

  entries_inheriting number(1not null,

  constraint unique_uk_3 unique(object_id_class,object_id_identity),

  constraint foreign_fk_1 foreign key(parent_object)references acl_object_identity(id),

  constraint foreign_fk_2 foreign key(object_id_class)references acl_class(id),

  constraint foreign_fk_3 foreign key(owner_sid)references acl_sid(id) );

 

create table acl_entry (

  id number not null primary key,

  acl_object_identity number not null,ace_order int not null,sid number not null,

  mask number(3not null,granting number(1not null,audit_success number(1not null,

  audit_failure number(1not null,

  constraint unique_uk_4 unique(acl_object_identity,ace_order),

  constraint foreign_fk_4 foreign key(acl_object_identity)

      references acl_object_identity(id),

  constraint foreign_fk_5 foreign key(sidreferences acl_sid(id) );

 

       新增记录时用于生成主键的sequence定义为:

  create or replace sequence seq_acl_sid start with increment by 1;

  create or replace sequence seq_acl_class start with increment by 1;

  create or replace sequence seq_acl_object_identity start with increment by 1;

  create or replace sequence seq_acl_entry start with increment by 1

 

1.2     表功能介绍

       如上所示,Spring Security的Acl功能需要使用到四张数据库表,分别为acl_sid、acl_class、acl_object_identity和acl_entry。

 

1.2.1表acl_sid

       表acl_sid的结构如下所示:

字段名

类型

说明

id

number

主键

sid

varchar

字符串类型的sid

principal

boolean

是否用户

 

       表acl_sid是用来保存Sid的。对于Acl而言,有两种类型的Sid,一种是基于用户的Sid,叫PrincipalSid;另一种是基于GrantedAuthority的Sid,叫GrantedAuthoritySid。acl_sid表的sid字段存放的是用户名或者是GrantedAuthority的字符串表示。prinpal是用来区分对应的Sid是用户还是GrantedAuthority的。正如在前文所描述的那样,Acl中对象的权限是用来授予给Sid的,Sid有用户和GrantedAuthority之分,所以我们的对象权限是可以用来授予给用户或GrantedAuthority的。

 

1.2.2表acl_class

       表acl_class的结构如下所示:

字段名

类型

说明

id

number

主键

class

varchar

对象类型的全限定名

 

       表acl_class是用来保存对象类型的,字段class中保存的是对应对象的全限定名。Acl需要使用它来区分不同的对象类型。

 

1.2.3表acl_object_identity

       表acl_object_identity的结构如下:

字段名

类型

描述

id

number

主键

object_id_class

number

关联acl_class,表示对象类型

object_id_identity

number

对象的主键,对于相同的class而言,其需要是唯一的。对象的主键默认需要是Long型,或者可以转换为Long型的对象,如Integer、Short等。

parent_object

number

父对象的id,关联acl_object_identity

owner_sid

number

拥有者的sid,关联acl_sid

entries_inheriting

boolean

是否继承父对象的权限。打个比方,删除对象childObj需要有delete权限,用户A他没有childObj的delete权限,但是他有childObj的父对象parentObj的delete权限,当entries_inheriting为true时,用户A同样可以删除childObj。

 

       表acl_object_identity是用来存放需要进行访问控制的对象的信息的。其保存的信息有对象的拥有者、对象的类型、对象的主键、对象的父对象和是否继承父对象的权限。

 

1.2.4表acl_entry

       表acl_entry的结构如下:

字段名

类型

说明

id

number

主键

acl_object_identity

number

对应acl_object_identity的id

ace_order

number

所属Acl的权限顺序

sid

number

对应acl_sid的id

mask

number

权限对应的掩码

granting

boolean

是否授权

audit_success

boolean

暂未发现其作用,Acl中有一个更新其值的方法,但未见被调用。

audit_failure

boolean

 

       表acl_entry是用于存放具体的权限信息的,从表结构我们也可以看出来,其描述的就是某个主体(Sid)对某个对象(acl_object_identity)是否(granting)拥有某种权限(mask)。当同一对象acl_object_identity在acl_entry表中拥有多条记录时,就会使用ace_order来标记对应的顺序,其对应于往Acl中插入AccessControlEntry时的位置,在进行权限判断时也是依靠ace_order的顺序来进行的,ace_order越小的越先进行判断。ace是Access Control Entry的简称。

 

1.3     Acl主要接口

       对于Acl而言,有两块比较核心的功能,一块是往对应的数据库表里面插数据,另一块是从数据库表里面取出对应的数据进行权限鉴定。要了解这些功能我们先来了解Acl中用到的主要接口。

 

l  Sid:可以用来表示一个principal,或者是一个GrantedAuthority。其对应的实现类有表示principal的PrincipalSid和表示GrantedAuthority的GrantedAuthoritySid。其信息会保存在acl_sid表中。

l  ObjectIdentity:ObjectIdentity表示Spring Security Acl中一个域对象,其默认实现类是ObjectIdentityImpl。ObjectIdentity并不是直接与acl_object_identity表相对应的,真正与acl_object_identity表直接相对应的是Acl。

l  Acl:每一个领域对象都会对应一个Acl,而且只会对应一个Acl。Acl是将Spring Security Acl中使用到的四个表串联起来的一个接口,其中会包含对象信息ObjectIdentity、对象的拥有者Sid和对象的访问控制信息AccessControlEntry。在Spring Security Acl中直接与acl_object_identity表相关联的是Acl接口,因为acl_object_identity表中的数据是通过保存Acl来进行的。一个Acl对应于一个ObjectIdentity,但是会包含有多个Sid和多个AccessControlEntry,即一个Acl表示所有Sid对一个ObjectIdentity的所有AccessControlEntry。Acl的默认实现类是AclImpl,该类实现Acl接口、MutableAcl接口、AuditableAcl接口和OwnershipAcl接口。

l  AccessControlEntry:一个AccessControlEntry表示一条访问控制信息,一个Acl中可以拥有多个AccessControlEntry。在Spring Security Acl中很多地方会使用ACE来简单的表示AccessControlEntry这个概念,比如insertAce其实表示的就是insert AccessControlEntry。每一个AccessControlEntry表示对应的Sid对于对应的对象ObjectIdentity是否被授权某一项权限Permission,是否被授权将使用granting进行区分。AccessControlEntry对应表acl_entry。

l  Permission:在Acl中使用一个bit掩码来表示一个Permission。Spring Security的Acl中默认使用的是BasePermission,其中已经定义了0-4五个bit掩码,分别对应于1、2、4、8、16,代表五种不同的Permission,分别是read (bit 0)、write (bit 1)、create (bit 2)、delete (bit 3)和administer (bit 4)。如果已经定义好的这五个bit掩码不能满足需求,我们可以对BasePermission进行扩展,也可以实现自己的Permission。Spring Security Acl默认的实现最多可以支持32个不同的掩码。

l  AclService:AclService是用来通过ObjectIdentity解析Acl的,其默认实现类是JdbcAclService。JdbcAclService底层操作是通过LookupStrategy来进行的,LookupStrategy的默认实现是BasicLookupStrategy。

l  MutableAclService:MutableAclService是用来对Acl进行持久化的,其默认实现类是JdbcMutableAclService。JdbcMutableAclService是继承自JdbcAclService的,所以我们可以同时通过JdbcMutableAclService对Acl进行读取和保存。如果我们希望自己来实现Acl信息的保存的话,我们也可以不使用该接口。

 

1.4     配置AclService

       AclService是使用Spring Security Acl功能的主入口。这里选择一个既可以从数据库读取Acl信息,又可以保存Acl信息到数据库的JdbcMutableAclService做示例。

       JdbcMutableAclService只有一个构造方法,它接收三个参数,DataSource、LookupStrategy和AclCache。其对应配置信息如下所示ÿ

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值