`
zhanshenny
  • 浏览: 261235 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Spring Security中的ACL

阅读更多
    ACL即访问控制列表(Access Controller List),它是用来做细粒度权限控制所用的一种权限模型。对ACL最简单的描述就是两个业务员,每个人只能查看操作自己签的合同,而不能看到对方的合同信息。
    一、准备数据库和aclService
    ACL所需的四张表,表结构见附录:附录 E, 数据库表结构。然后我们需要配置aclService,它负责与数据库进行交互。
CREATE TABLE `acl_sid` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `principal` tinyint(1) NOT NULL,
  `sid` varchar(100) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_uk_1` (`sid`,`principal`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;

CREATE TABLE `acl_class` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `class` varchar(100) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_uk_2` (`class`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

CREATE TABLE `acl_object_identity` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `object_id_class` bigint(20) NOT NULL,
  `object_id_identity` bigint(20) NOT NULL,
  `parent_object` bigint(20) DEFAULT NULL,
  `owner_sid` bigint(20) NOT NULL,
  `entries_inheriting` tinyint(1) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_uk_3` (`object_id_class`,`object_id_identity`),
  KEY `foreign_fk_1` (`parent_object`),
  KEY `foreign_fk_3` (`owner_sid`),
  CONSTRAINT `acl_object_identity_ibfk_1` FOREIGN KEY (`parent_object`) REFERENCES `acl_object_identity` (`id`),
  CONSTRAINT `acl_object_identity_ibfk_2` FOREIGN KEY (`object_id_class`) REFERENCES `acl_class` (`id`),
  CONSTRAINT `acl_object_identity_ibfk_3` FOREIGN KEY (`owner_sid`) REFERENCES `acl_sid` (`id`)

CREATE TABLE `acl_entry` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `acl_object_identity` bigint(20) NOT NULL,
  `ace_order` int(11) NOT NULL,
  `sid` bigint(20) NOT NULL,
  `mask` int(11) NOT NULL,
  `granting` tinyint(1) NOT NULL,
  `audit_success` tinyint(1) NOT NULL,
  `audit_failure` tinyint(1) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_uk_4` (`acl_object_identity`,`ace_order`),
  KEY `foreign_fk_5` (`sid`),
  CONSTRAINT `acl_entry_ibfk_1` FOREIGN KEY (`acl_object_identity`) REFERENCES `acl_object_identity` (`id`),
  CONSTRAINT `acl_entry_ibfk_2` FOREIGN KEY (`sid`) REFERENCES `acl_sid` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

这四个表的说明如下:
?
1、ACL_SID让我们定义系统中唯一主体或授权(“SID”意思是“安全标识”——Spring Security Identity),是ACL认证对象。 它包含的列有ID,一个文本类型的SID,以及principal。
??? 其中,SID是Security ID的简称,表示一个被认证对象。记录一个用户名(USERBASE.NAME)或角色名(ROLES.NAME) 。如果按角色认证,SID就是对应的角色,如果按用户名认证,SID就是对应的用户名。用来表示是否使用文本显示引用的主体名或一个GrantedAuthority。
??? 而principal是认证规则。1 SID为用户名,0 SID为角色名。因此,对每个唯一的主体或GrantedAuthority都有单独一行。 在使用获得授权的环境下,一个SID通常叫做"recipient"授予者。
?
2、ACL_CLASS 让我们在系统中确定唯一的领域对象类。包含的列有ID和java类名。 因此,对每个我们希望保存ACL权限的类都有单独一行。其中,class是所要操作的域对象类型,它是域对象类型的全限定名。只有在此表中的CLASS,才被准许进行ACL授权及验证。
?
3、ACL_OBJECT_IDENTITY 为系统中每个唯一的领域对象实例保存信息。 列包括ID,指向ACL_CLASS的外键,唯一标识,所以我们知道为哪个ACL_CLASS实例提供信息,parent,一个外键指向ACL_SID 表,展示领域对象实例的拥有者,我们是否允许ACL条目从任何父亲ACL继承。 我们对每个领域对象实例有一个单独的行,来保存ACL权限。



    1. 为acl配置cache
    默认使用ehcache,spring security提供了一些默认的实现类。
<bean id="aclCache" class="org.springframework.security.acls.jdbc.EhCacheBasedAclCache">
    <constructor-arg ref="aclEhCache"/>
</bean>
<bean id="aclEhCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
    <property name="cacheManager" ref="cacheManager"/>
    <property name="cacheName" value="aclCache"/>
</bean>
    在ehcache.xml中配置对应的aclCache缓存策略。
<cache
    name="aclCache"
    maxElementsInMemory="1000"
    eternal="false"
    timeToIdleSeconds="600"
    timeToLiveSeconds="3600"
    overflowToDisk="true"
/>

    2. 配置lookupStrategy
    简单来说,lookupStrategy的作用就是从数据库中读取信息,把这些信息提供给aclService使用,所以我们要为它配置一个dataSource,配置中还可以看到一个aclCache,这就是上面我们配置的缓存,它会把资源最大限度的利用起来。
<bean id="lookupStrategy" class="org.springframework.security.acls.jdbc.BasicLookupStrategy">
    <constructor-arg ref="dataSource"/>
    <constructor-arg ref="aclCache"/>
    <constructor-arg>
        <bean class="org.springframework.security.acls.domain.AclAuthorizationStrategyImpl">
            <constructor-arg>
                <list>
                    <ref local="adminRole"/>
                    <ref local="adminRole"/>
                    <ref local="adminRole"/>
                </list>
            </constructor-arg>
        </bean>
    </constructor-arg>
    <constructor-arg>
        <bean class="org.springframework.security.acls.domain.ConsoleAuditLogger"/>
    </constructor-arg>
</bean>
<bean id="adminRole" class="org.springframework.security.GrantedAuthorityImpl">
    <constructor-arg value="ROLE_ADMIN"/>
</bean>
    中间一部分可能会让人感到困惑,为何一次定义了三个adminRole呢?这是因为一旦acl信息被保存到数据库中,无论是修改它的从属者,还是变更授权,抑或是修改其他的ace信息,都需要控制操作者的权限,这里配置的三个权限将对应于上述的三种修改操作,我们把它配置成,只有ROLE_ADMIN才能执行这三种修改操作。
   
    3. 配置aclService
    当我们已经拥有了dataSource, lookupStrategy和aclCache的时候,就可以用它们来组装aclService了,之后所有的acl操作都是基于aclService展开的。
    <bean id="aclService"  class="org.springframework.security.acls.jdbc.JdbcMutableAclService">
    <constructor-arg ref="dataSource"/>
    <constructor-arg ref="lookupStrategy"/>
    <constructor-arg ref="aclCache"/>
</bean>

二、使用aclService管理acl信息
    当我们添加了一条信息,要在acl中记录这条信息的ID,所有者,以及对应的授权信息。下列代码在添加信息后执行,用于添加对应的acl信息。
ObjectIdentity oid = new ObjectIdentityImpl(Message.class, message.getId());
MutableAcl acl = mutableAclService.createAcl(oid);
acl.insertAce(0, BasePermission.ADMINISTRATION,
    new PrincipalSid(owner), true);
acl.insertAce(1, BasePermission.DELETE,
    new GrantedAuthoritySid("ROLE_ADMIN"), true);
acl.insertAce(2, BasePermission.READ,
    new GrantedAuthoritySid("ROLE_USER"), true);
mutableAclService.updateAcl(acl);
第一步,根据class和id生成object的唯一标示。
第二步,根据object的唯一标示,创建一个acl。
第三步,为acl增加ace,这里我们让对象的所有者拥有对这个对象的“管理”权限,让“ROLE_ADMIN”拥有对这个对象的“删除”权限,让“ROLE_USER”拥有对这个对象的“读取”权限。
最后,更新acl信息。
当我们删除对象时,也要删除对应的acl信息。下列代码在删除信息后执行,用于删除对应的acl信息。
ObjectIdentity oid = new ObjectIdentityImpl(Message.class, id);
mutableAclService.deleteAcl(oid, false);
使用class和id可以唯一标示一个对象,然后使用deleteAcl()方法将对象对应的acl信息删除。

三、使用acl控制delete操作
述代码中,除了对象的拥有者之外,我们还允许“ROLE_ADMIN”也可以删除对象,但是我们不会允许除此之外的其他用户拥有删除对象的权限,为了限制对象的删除操作,我们需要修改Spring Security的默认配置。
首先要增加一个对delete操作起作用的表决器。
<bean id="aclMessageDeleteVoter" class="org.springframework.security.vote.AclEntryVoter">
    <constructor-arg ref="aclService"/>
    <constructor-arg value="ACL_MESSAGE_DELETE"/>
    <constructor-arg>
        <list>
            <util:constant static-field="org.springframework.security.acls.domain.BasePermission.ADMINISTRATION"/>
            <util:constant static-field="org.springframework.security.acls.domain.BasePermission.DELETE"/>
        </list>
    </constructor-arg>
    <property name="processDomainObjectClass" value="com.family168.springsecuritybook.ch12.Message"/>
</bean>
它只对Message这个类起作用,而且可以限制只有管理和删除权限的用户可以执行删除操作。
然后要将这个表决器添加到AccessDecisionManager中。
<bean id="aclAccessDecisionManager" class="org.springframework.security.vote.AffirmativeBased">
    <property name="decisionVoters">
        <list>
            <bean class="org.springframework.security.vote.RoleVoter"/>
            <ref local="aclMessageDeleteVoter"/>
        </list>
    </property>
</bean>

现在AccessDecisionManager中有两个表决器了,除了默认的RoleVoter之外,又多了一个我们刚刚添加的aclMessageDeleteVoter。
现在可以把新的AccessDecisionManager赋予全局方法权限管理器了。
<global-method-security secured-annotations="enabled"
    access-decision-manager-ref="aclAccessDecisionManager"/>

然后我们就可以在MessageService.java中使用Secured注解,控制删除操作了。
@Transactional
@Secured("ACL_MESSAGE_DELETE")
public void remove(Long id) {
    Message message = this.get(id);
    list.remove(message);
    ObjectIdentity oid = new ObjectIdentityImpl(Message.class, id);
    mutableAclService.deleteAcl(oid, false);
}

实际上,我们最好不要让没有权限的操作者看到remove这个链接,可以使用taglib隐藏当前用户无权看到的信息。
<sec:accesscontrollist domainObject="${item}" hasPermission="8,16">
      |
      <a href="message.do?action=remove&id=${item.id}">Remove</a>
</sec:accesscontrollist>
       
8, 16是acl默认使用的掩码,8表示DELETE,16表示ADMINISTRATOR,当用户不具有这些权限的时候,他在页面上就看不到remove链接,也就无法执行操作了。
这比让用户可以执行remove操作,然后跑出异常,警告访问被拒绝要友好得多。

四、控制用户可以看到哪些信息
当用户无权查看一些信息时,我们需要配置afterInvocation,使用后置判断的方式,将用户无权查看的信息,从MessageService返回的结果集中过滤掉。

后置判断有两种形式,一种用来控制单个对象,另一种可以过滤集合。
<bean id="afterAclRead" class="org.springframework.security.afterinvocation.AclEntryAfterInvocationProvider">
    <sec:custom-after-invocation-provider/>
    <constructor-arg ref="aclService"/>
    <constructor-arg>
        <list>
            <util:constant static-field="org.springframework.security.acls.domain.BasePermission.ADMINISTRATION"/>
            <util:constant static-field="org.springframework.security.acls.domain.BasePermission.READ"/>
        </list>
    </constructor-arg>
</bean>
<bean id="afterAclCollectionRead" class="org.springframework.security.afterinvocation.AclEntryAfterInvocationCollectionFilteringProvider">
    <sec:custom-after-invocation-provider/>
    <constructor-arg ref="aclService"/>
    <constructor-arg>
        <list>
            <util:constant static-field="org.springframework.security.acls.domain.BasePermission.ADMINISTRATION"/>
            <util:constant static-field="org.springframework.security.acls.domain.BasePermission.READ"/>
        </list>
    </constructor-arg>
</bean>
       
afterAclRead可以控制单个对象是否可以显示,afterAclCollectionRead则用来过滤集合中哪些对象可以显示。[6]
对这两个bean都是用了custom-after-invocation-provider标签,将它们加入的后置判断的行列,下面我们为MessageService.java中的对应方法添加Secured注解,之后它们就可以发挥效果了。
@Secured({"ROLE_USER", "AFTER_ACL_READ"})
public Message get(Long id) {
    for (Message message : list) {
        if (message.getId().equals(id)) {
            return message;
        }
    }
    return null;
}
@Secured({"ROLE_USER", "AFTER_ACL_COLLECTION_READ"})
public List getAll() {
    return list;
}
       
以上就是Spring Security支持的ACL,我们只演示了DELETE一种情况,就已经编写了如此之多的xml配置文件,很难想象随着对象的增多,这个配置工作要扩展到什么程度,如何才能像之前配置user和resource时,将这些acl的信息都配置到database中呢?目前还是一个我们正在考虑的问题。
分享到:
评论

相关推荐

    spring security acl 实例

    spring security acl 代码实例 spring security acl 代码实例spring security acl 代码实例spring security acl 代码实例spring security acl 代码实例spring security acl 代码实例

    基于Spring Security的ACL实现与扩展ppt

    基于Spring Security的ACL实现与扩展ppt(徐会生著),用ppt2003可打开

    spring-security-acl-2.0.4.jar

    spring-security-acl-2.0.4.jar

    spring security acl

    用spring security实现了acl权限控制。因为文件大小问题去掉了lib。

    SpringSecurity.zip

    它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制...

    spring security3.0.4 的acl使用例子

    spring security3.0.4 的acl使用例子,相关的说明在 http://blog.csdn.net/lhx1026/archive/2010/11/22/6027125.aspx

    spring-security 官方文档 中文版

    spring security官方文档 中文版 看了下翻译 还是可以的 比其他查到的专业点 希望可以帮助到大家

    spring security acl 3.1.4 REALEASE.jar

    spring security 3.1.4的release包 需要的可以拿走

    spring-security-acl-neo4j:带有 Neo4j 图形数据库的 Spring Security Acl 支持库

    spring-security-acl-neo4j 带有 Neo4j 图形数据库的 Spring Security Acl 支持库动机该项目背后的动机是通过消除使用传统 RDBMS 作为后端数据存储创建的瓶颈来提高 Spring Security ACL 的性能。 阅读这篇了解更多...

    Spring Security 中文教程.pdf

    5.5. Spring Security中的访问控制(验证) 5.5.1. 安全和AOP建议 5.5.2. 安全对象和AbstractSecurityInterceptor 5.5.2.1. 配置属性是什么? 5.5.2.2. RunAsManager 5.5.2.3. AfterInvocationManager ...

    spring security jar包

    spring-security-acl3.14RELESE.jar spring-security-acl-3.14RELESE-javadoc.jar spring-security-acl-3.14RELESE-sources.jar

    SpringSecurity2.0.5

    SpringSecurity2.0.5全是jar包

    spring security 所需要jar包

    spring-security-acl-2.0.4.jar spring-security-core-2.0.4.jar spring-security-core-tiger-2.0.4.jar spring-security-taglibs-2.0.4.jar spring-support-2.0.8.jar spring-web-2.0.8.jar spring-webmvc-2.0.8....

    spring-security-acl-2.0.5.RELEASE.jar

    spring-security-acl-2.0.5.RELEASE.jar

    spring security3.0 源码

    spring-security-web-3.0 spring-security-taglibs-3.0 spring-security-openid-3.0 spring-security-core-3.0 spring-security-config-3.0 spring-security-aspects-3.0 spring-security-acl-3.0

    spring security3基本包

    spring-security-acl-3.0.5.RELEASE.jar spring-security-config-3.0.5.RELEASE.jar spring-security-core-3.0.5.RELEASE.jar spring-security-taglibs-3.0.5.RELEASE.jar spring-security-web-3.0.5.RELEASE....

    springSecurity3中文文档

    第二章:springsecurity起步 第三章:增强用户体验 第四章:凭证安全存储 第五章:精确的访问控制 第六章:高级配置和扩展 第七章:访问控制列表(ACL) 第八章:对OpenID开放 第九章:LDAP目录服务 第十章:使用...

    SpringSecurity3.1源代码

    进行spring security开发引用的spring-security-acl-3.0.2.RELEASE.jar、spring-security-config-3.0.2.RELEASE.jar、spring-security-core-3.0.2.RELEASE.jar、spring-security-taglibs-3.0.2.RELEASE.jar、spring-...

    spring-security-acl-mongodb:基于 Spring Security MongoDB 的访问控制列表 (ACL) 实现

    Spring Security ACL MongoDB Spring Security 访问控制列表 (ACL) 是一种方便的方式来授予对域对象(例如书籍或联系人列表)的基于用户的权限访问。 默认情况下,Spring Security通过4个SQL表管理ACL,这些SQL表在...

Global site tag (gtag.js) - Google Analytics