您的位置:首页 > 编程语言 > Java开发

SpringSecurity ACL持久化: Hibernate implementation of Spring Security ACL

2010-04-07 23:55 721 查看
本文重点描述如何基于hibernate在micrite

实现SS(Spring Security) ACL,相关软件版本为 spring-security-2.0.5.RELEASE
micrite-0.11
。实现
的过程中,借鉴了下面三个例子:

contacts
联系人管理(重点参考)

SS 的官方例子,控制不同用户对联系人的查看、修改、删除、管理权限。

dms
文档管理系统

SS 的官方例子,和contract相比,功能相对简单,主要是体现了ACL继承的概念,例如文档的ACL权限可继承自所在目录的权限。

springstart
职员、客户的帐户管理(重点参考)

denksoft 提供的基于postgresql的例子,有详细的说明文档


它们都采用SS默认的JDBC对ACL数据做持久化,而micrite持久层采用hibernate,如要实现ACL,需要重新实现SS默认的
ACL数据持久化接口,否则一个系统里就会有两种持久化方式(就像springstart一样),这有点难以接受。

SS的开发组曾对这个问题做过讨论,似乎短期内都没有修改的计划,所以,只能自己动手了。

建表

实现ACL需要建下面4张表:
acl_sid

acl_class

acl_object_identity

acl_entry


表结构的说明请参考 Schema
Documentation
和 ER
Diagram
(基于derby)。

micrite使用velocity
模板
生成多种数据库脚本,保存在安装包的如下目录。
path: ./dbscripts


创建实体类

除了为上面的4张表建立相应的实体类之外,再建一个抽象类AbstractSecureObject

目的是如果有多个受ACL保护的对象,不用在
applicationContext-security.xml

文件里一一配
置,只需配置一个AbstractSecureObject,让其他受保护的实体类继承它。

AbstractSecureObject 只需要一个ID属性,让ACL可以获得受保护对象实例的ID值。

package org.gaixie.micrite.beans

增加DAO

为每个ACL实体类增加相应的DAO接口,及实现类。

package org.gaixie.micrite.security.dao
IAclSidDAO.java

IAclClassDAO.java

IAclObjectIdentityDAO.java

IAclEntryDAO.java

package org.gaixie.micrite.security.dao.hibernate
AclSidDAOImpl.java

AclClassDAOImpl.java

AclObjectIdentityDAOImpl.java

AclEntryDAOImpl.java

方法的说明请参见 micrite
API文档


实现ACL数据持久化接口

我们需要实现两个ACL负责数据持久化的接口:

AclService
负责ACL实例的读取。

MutableAclService
负责创建和存储ACL实例。

首先,先创建一个我们自己的接口 ISecurityAclService

目的是当新增一个受保护的对象实例时,统一调用此接口实现权限信息的持久化,同时让它继承SS的MutableAclService接口,所有下面会提
到。

接下来,创建两个Acl的数据持久化接口的实现类:

package org.gaixie.micrite.security.service.impl
AclServiceImpl.java

MutableAclServiceImpl.java

AclServiceImpl

重点是重新实现AclService接口的一个方法
public Map readAclsById(ObjectIdentity[] objects, Sid[] sids);


SS中此方法默认实现,是通过调用一个名为BasicLookupStrategy

类来完成ACL实例信息的读取,这里我们直接通过调用相关的DAO,来实现此功能。省去BasicLookupStrategy类的原因是SS基于
JDBC获取数据,除了需要一些ANSI
SQL之外,还要将得到的ResultSet结果集转换为相应的ACL实例,而我们采用Hibernate,直接通过DAO取出来就是对象实例,代码要比
默认的实现简单很多。(总算体现出Hibernate的好处了!!!)

MutableAclServiceImpl

此类所有方法都需要基于hibernate重写,由于它实现的是自定义的ISecurityAclService接口,所以要比SS默认的JDBC多实现
两个方法:
public void addPermission(AbstractSecureObject securedObject

    , Permission permission, Class clazz);

public void addPermission(AbstractSecureObject securedObject

    , Sid recipient, Permission permission, Class clazz);


如果你了解上面ACL4个实体类的含义,并且熟悉Hibernate,会很容易理解这两个实现类,可以对照SS默认的JDBC实现。

当前micrite还没有实现AclCache接口,它可以大幅提升获取Acl实例的性能。

修改相关的xml配置文件

最后修改两个配置文件。

applicationContext-security.xml

此配置文件相比没有ACL之前,主要是增加了afterInvocationManager的相关内容,用来处理在被拦截方法执行后,对返回的结果集进行
ACL过滤。

applicationContext-security-bean.xml

此配置文件唯一需要注意的是 securityMutableAclService
,它实际对应着SS配置文件中的aclService,他们都是ACL数据持久化接口MutableAclService的实现类,由于我们采用
Spring自动装载的方式,所以不需要构造参数。它在
applicationContext-security.xml

文件
中被频繁引用。

增加一个角色
AFTER_ACL_COLLECTION_READ

,以后所有需要进行ACL结果集过滤的方法都绑定到此
角色。

到目前为止,我们已经完成了所有的ACL修改。

测试ACL

下面的步骤将实现:不同的用户只能看到自己拥有在的角色。管理员组(ROLE_ADMIN)可以看到所有的角色。

选择一个要进行ACL保护的实体类Role

让Role继承AbstractSecureObject

添加要拦截的方法并绑定到角色
AFTER_ACL_COLLECTION_READ

,通过界面或者SQL命令都可以。
注意拦截的方法至少有一个是返回Role对象结果集,如
List(Role)

Set(Role)

等。
可参见:

修改RoleServiceImpl

中的
add(..), delete(..)

方法,在增加或删除Role之后,也增加或删除相应的ACL对象。通过调用
ISecurityAclServicede的方法可以很简单的实现。

编译、运行修改后的代码,用admin登录系统,增加几个Role和User,然后用不同的User登录,看看结果是否正确。

参考文档

[1] http://code.google.com/p/micrite/wiki/Permissions

[2] http://en.wikipedia.org/wiki/Access_Control_List
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐