`
lengyun3566
  • 浏览: 452026 次
  • 性别: Icon_minigender_1
  • 来自: 大连
博客专栏
D59180b9-02f1-3380-840c-ea34da46143c
《Spring Secur...
浏览量:383044
社区版块
存档分类
最新评论

《Spring Security3》第七章第二部分翻译(高级ACL)(下)

阅读更多

 

支持ACLSpring表达式语言

 

SpELACL系统的支持仅限于方法安全,通过使用hasPermission SpEL方法。典型情况下,这种类型的访问检查会与引用一个或多个传入参数(进行@PreAuthorize检查)或集合过滤(进行@PostAuthorize检查)联合使用。

         遗憾的是,启用ACL方法安全配置需要我们配置所有的方法安全以明确的Spring Bean的方式。这样,我们就需要我们移除<global-method-security>元素并替换为我们在第六章中介绍过的明确方式配置方法安全。鉴于我们这里不想重复配置(尽管它包含在本章代码中),我们所要做的只是做一下如下的细微修改,ACL hasPermission检查所需要的类就可用了:

 

<bean class="org.springframework.security.access.expression.method.
DefaultMethodSecurityExpressionHandler" id="methodExprHandler">
  <property name="permissionEvaluator" ref="aclPermissionEvaluator"/>
</bean>
<bean class="org.springframework.security.acls.AclPermissionEvaluator" 
id="aclPermissionEvaluator">
  <constructor-arg ref="aclService"/>
  <property name="permissionFactory" ref="customPermissionFactory"/>
</bean>

 我们更新的methodExprHandlerbean定义,配置了o.s.s.access.PermissionEvaluator的实现(默认的PermissionEvaluator实现会拒绝所有的许可认证检查)。o.s.s.acls.AclPermissionEvaluator使用了AclService及相关的类去实际检查SpEL表达式声明的许可权限。

         随着配置完成,我们可以使用一个替代的方法来过滤显示在首页上的分类列表(确保你已经移除了上一个练习所添加的tag库)。

【注意,hasPermission方法不再支持逗号分隔的许可授权(正如我们在<accesscontrollist> JSP tag中见到的那样),所以我们需要使用SpEL的布尔逻辑。】

         只需简单的添加以下声明到IProductService接口上:

 

@PostFilter("hasPermission(filterObject, 'READ') or hasPermission(filterObject, 'ADMIN_READ')")
Collection<Category> getCategories();

 现在,重启应用并比较以匿名用户、adminadmin2进入时首页的分类列表。注意这个显示列表是如何通过ACL许可授权完成的?我们可以看到SpELhasPermission方法很好的与使用ACL的应用通过方法安全注解结合起来。

易变的ACLMutable ACLs)和授权

         尽管JBCP Pets站点没有实现完整的用户用户管理功能,但是你的应用可能会有这些通用的功能如:新用户注册以及管理用户维护。到此时,缺少这些功能——我们是通过在应用初始化的时候用SQL插入的方法代替的——并没有阻止我们演示Spring SecuritySpring ACL的很多功能。

         但是,在运行时适当的处理声明的ACL、添加或删除系统用户,对于基于ACL的授权环境来说保证一致性和安全很重要。Spring ACL通过易变的ACLo.s.s.acls.model.MutableAcl)来解决这个问题。

         扩展自Acl接口的MutableAcl允许运行时操作ACL域以实现修改某个特定ACL的内存表现。这个功能包括新增、更新以及删除ACE,修改ACE的拥有者和其它有用的功能。

         那么,我们可能会期望Spring ACL模块能够有内置的方式将运行时的ACL变化持久化到JDBC数据存储中,它确实如此。o.s.s.acls.jdbc.JdbcMutableAclService能用来创建、更新和删除数据库中的MutableAcl实例,并且管理其它支持ACL的表(能够处理SIDObjectIdentity以及域对象类名)。

         对我们来说,它只需要一个简单的配置来使用JdbcMutableAclService替换JdbcAclService——易变service需要一个对ACL缓存的引用,这样它就能够在更新数据库条目的时候将缓存删除。这个bean的配置很简单:

 

<bean class="org.springframework.security.acls.jdbc.JdbcMutableAclService"
 id="mutableAclService">
  <constructor-arg ref="dataSource"/>
  <constructor-arg ref="lookupStrategy"/>
  <constructor-arg ref="aclCache"/>
</bean>

 请回忆在本章前面,AclAuthorizationStrategyImpl允许我们指定对易变ACL进行操作所需要的角色。它们以bean配置的方式提供给构造方法。构造参数以及它们的意义,如下:

 

参数序号

做什么的

1

表明安全实体要修改ACL保护对象拥有者所要拥有的角色

2

表明安全实体要修改ACL保护对象审计所要拥有的角色

3

表明安全实体要对ACL保护对象进行其它修改(新建、更新和删除)所要拥有的角色

译者注:以上的三个参数的作用就是要保证对保护的对象进行操作时,登录人必须有足够的权限。

JdbcMutableAclService包含一系列的方法在运行时来操作ACLACE数据。尽管这些方法本身很容易理解(createAclupdateAcldeleteAcl),但是正确的配置和使用JdbcMutableAclService经常对Spring Security的高级用户都很困难。

让我们实现一个ACL启动类它会替换我们的启动脚本,并用代码的方式插入当前的ACLACE条目(以及支持的ObjectIdentitySid)。

 

配置Spring事务管理器

JdbcMutableAclService使用SpringJdbcTemplate来与JDBC DataSource进行交互。所以,它需要一个Spring JDBC PlatformTransactionManager以保证(很有侵入性)所有与数据库的交互正确地包装在事务中。

大多数实际使用Spring的应用可能已经有一个声明的事务管理器,但是我们的JBCP Pets应用并没有。我们在dogstore-base.xml添加一个:

 

<bean id="txManager"
 class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource"/>
</bean> 

声明一个对启动类的应用,一会将会对它进行编码:

<bean class="com.packtpub.springsecurity.security.AclBootstrapBean" 
init-method="aclBootstrap"/> 

很像在第四章:凭证安全存储中的DatabasePasswordSecurerBean,我们配置这个bean使得Spring ApplicationContext初始化时,aclBootstrap方法会被触发——恰当的时间来启动我们应用中的ACL数据。

JdbcMutableAclService交互

         现在,我们要编写启动bean——创建com.packtpub.springsecurity.security.AclBootstrapBean类。首先我们使用@Autowired注入需要的依赖:

package com.packtpub.springsecurity.security;
// imports omitted
public class AclBootstrapBean {
  @Autowired
  MutableAclService mutableAclService;
  @Autowired
  IProductDao productDao;
  @Autowired
  PlatformTransactionManager transactionManager; 

   接下来是方法的实际定义,它将会被触发以启动ACL数据——我们将会每次分析一个片段:

 

public void aclBootstrap() {
// domain data to set up
Collection<Category> categories = productDao.getCategories();
Iterator<Category> iterator = categories.iterator();
final Category category1 = iterator.next();
final Category category2 = iterator.next();

 我们需要引用实际要保护的域对象以便于为它们创建ACL。回忆一下,我们的ACL启动SQL只对前两个分类添加条目,所以我们要把它们从ProductDAO中取出来。

         JdbcMutableAclService需要使用ObjectIdentity来创建初始的MutableAcl(它能够被进一步的管理,我们等会能看到)。为了创建ObjectIdentity,我们需要真正的域对象。

 

// needed because MutableAclService requires a current authenticated principal
GrantedAuthorityImpl roleUser = new GrantedAuthorityImpl("ROLE_USER");
GrantedAuthorityImpl roleAdmin = new GrantedAuthorityImpl("ROLE_ADMIN");
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("admin","admin",Arrays.asList(new GrantedAuthority[]{roleUser, roleAdmin}));
SecurityContextHolder.getContext().setAuthentication(token);

 JdbcMutableAclService会验证一个用户已经登录,并将其作为建立的MutableAcl的默认拥有者。遗憾的是,这是一个强制检查,即便随后你明确设置ACL拥有者(也不行)。因为这些代码执行时没有认证过的用户,所以我们让JdbcMutableAclServiceadmin用户作为当前认证过的用户(译者注:就是上面最后两句代码)。

 

// sids
final Sid userRole = new GrantedAuthoritySid("ROLE_USER");
final Sid adminRole = new GrantedAuthoritySid("ROLE_ADMIN");
// users
final Sid adminUser = new PrincipalSid("admin");
final Sid admin2User = new PrincipalSid("admin2");

 我们需要为安全实体和组创建Sid,它们是ACLACE的结构,所以在这里我们明确创建它们。记住的是,如果你在应用范围内管理ACL(例如,通过UI层调用业务服务完成),你可以以不同的方式处理这个问题——这里的代码只是一个例子,我们鼓励你根据情况作出调整。

 

// all interaction with JdbcMutableAclService must be within a 
transaction
TransactionTemplate tt = new TransactionTemplate(transactionManager); 
  tt.execute(new TransactionCallbackWithoutResult() {
  @Override
  protected void doInTransactionWithoutResult(TransactionStatus arg0) 
{
  // category 1 ACL
  MutableAcl createAclCategory1 = mutableAclService.createAcl(new Obje
ctIdentityImpl(category1));
  createAclCategory1.setOwner(adminRole);
  createAclCategory1.insertAce(0, BasePermission.READ, adminRole, 
true);
  mutableAclService.updateAcl(createAclCategory1);
  // category 2 ACL
  MutableAcl createAclCategory2 = mutableAclService.createAcl(new Obje
ctIdentityImpl(category2));
  createAclCategory2.setOwner(admin2User);
  createAclCategory2.insertAce(0, CustomPermission.ADMIN_READ, 
admin2User, true);
  mutableAclService.updateAcl(createAclCategory2);
}});
SecurityContextHolder.clearContext();
}
} 

在一个新的事务范围内,与JdbcMutableAclService的交互完成了。我们可以看到初始的createAcl调用返回一个MutableAcl。在这背后,针对ObjectIdentitySid进行了数据库插入和查找。MutableAcl本身提供了方法来创建、更新和删除ACL中的ACE(记住,ACE声明的是单个的权限-SID匹配)。最后MutableAcl通过updateAcl方法调用更新到数据库中。

         要注意的是JdbcMutableAclService还负责确保MutableAcl操作进行时,AclCache被更新。

         建议你体验易变的ACL服务并增强这个站点以支持用户的新建和编辑——JdbcMutableAclService有很好的文档(在代码层面),尝试实现它会是一个很好的练习,这取决于你是否愿意实现完整的运行时驱动的ACL模型。

Ehcache ACL缓存

         Ehcache是一个开源的、内存和基于硬盘的缓存库,它被广泛用在很多开源和商用Java产品中。正如我们在本章前面提到的,Spring Security提供了一个默认的ACL缓存实现,它依赖于一个配置的Ehcache实例,它会存储ACL信息并优先于在数据库中读取ACL

         鉴于在本节我们不想过多介绍详细配置Ehcache,我们将会涉及到Spring ACL如何使用cache并介绍一个简单的默认配置。

配置Ehcache ACL缓存

         建立Ehcache很简单——我们需要简单地声明两个Spring Corebean,它们管理Ehcache实例并暴露几个有用的配置属性:

<bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" 
id="ehCacheManagerBean"/>
<bean class="org.springframework.cache.ehcache.EhCacheFactoryBean" 
id="ehCacheFactoryBean">
  <property name="cacheManager" ref="ehCacheManagerBean"/>
</bean> 

  接下来,我们要实例化Ehcache ACL缓存bean

 

<bean class="org.springframework.security.acls.domain.EhCacheBasedAclCache"
 id="ehCacheAclCache">
  <constructor-arg ref="ehCacheFactoryBean"/>
</bean>

 最后,我们将NullAclCache实现替换为基于Ehcache的实现:

 

<bean class="org.springframework.security.acls.jdbc.BasicLookupStrategy" id="lookupStrategy">
  <constructor-arg ref="dataSource"/>
  <constructor-arg ref="ehCacheAclCache"/>
  <constructor-arg ref="aclAuthzStrategy"/>
  <constructor-arg ref="aclAuditLogger"/>
</bean>

 当这些配置完成(并且Ehcache运行时JAR在你的classpath中),ACL数据将会基于Ehcache缓存管理器的配置进行缓存。

Spring ACL怎样使用Ehcache

         前面介绍的配置步骤可能会比较简单,添加Ehcache到你的应用中——尤其是大量使用——要进行细致的分析,比较缓存的成本和数据库查询的成本。理解EhcacheSpring ACL中是如何使用的对于规划缓存大小和寿命很重要。

         作为ACL缓存策略的一部分,Spring ACL将会存储以下所有的对象(它们的大多数在o.s.s.acls.domain)到缓存中,要么作为key要么作为值:

l  ObjectIdentity(实现类为ObjectIdentityImpl);

l  Sid(实现类为GrantedAuthoritySidPrincipalSid);

l Acl(实现类为AclImpl),包含AccessControlEntry (实现类为AccessControlEntryImpl);

l  你对象实例的Serializable类型主键(一般为Long,除非你对Spring ACL运行时类做了重要的个性化)

只有BasicLookupStrategyMutableAclServiceACL缓存机制的用户,使用缓存很简单。关于缓存中条目的大小,比较好的办法是在合适的负载测试中监控缓存以评估缓存元素的内存使用和存在寿命。

如果你的应用为了其它的目的(如Hibernate或其它ORM根据)已经使用了Ehcache,你可能愿意将用于ORM目的的缓存实例和用于存储ACL数据的缓存实例区分开来。一般的做法是在构建用于Spring ACLEhCacheFactoryBean时,提供唯一的cache名,如下:

 

<bean class="org.springframework.cache.ehcache.EhCacheFactoryBean" 
id="ehCacheFactoryBean">
  <property name="cacheManager" ref="ehCacheManagerBean"/>
  <property name="cacheName" value="springAclCacheRegion"/>
</bean>

 奇怪的是,除了Javadoc以外,Spring Core中对于Ehcache的支持没有任何正规的文档。如果使用Spring ACLEhcache对你很重要,那你很可能需要自己深入研读代码。

 

 

 

 

3
0
分享到:
评论

相关推荐

    Spring Security 资料合集

    这三份资料——"实战Spring Security 3.x.pdf"、"Spring Security 3.pdf" 和 "Spring Security使用手册.pdf" 将深入探讨这些概念,并提供实践指导,帮助读者掌握如何在实际项目中应用Spring Security。通过学习这些...

    springSecurity3中文文档

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

    SpringSecurity笔记,编程不良人笔记

    - OAuth2:SpringSecurity支持OAuth2协议,实现第三方登录和API保护。 - JWT(JSON Web Tokens):可使用JWT进行状态less的认证,提高系统的可扩展性。 - CORS(Cross-Origin Resource Sharing):SpringSecurity...

    spring security 入门经典教程

    - 第2章:介绍了Spring Security的概况,可能包括了Spring Security的基本功能、特性以及它如何帮助开发者保护应用程序。 - 第3章:Spring Security架构与设计,这一章节着重讲述Spring Security的内部架构和设计...

    springsecurity所有jar包

    2. **spring-security-core**:这是Spring Security的基础模块,提供了安全核心服务,如安全性上下文、访问决策管理器、权限评估器等。它实现了基于角色的访问控制(RBAC)模型,处理用户、权限、角色等核心概念。 ...

    Pro+Spring+Security

    第二章:介绍Spring Security(Introducing Spring Security) - Spring Security概述:解释Spring Security框架的作用以及如何在Spring应用中集成安全功能。 - 基础配置:介绍如何设置Spring Security的基本配置,...

    Spring Security权限管理开发手册

    - **第2章:使用数据库管理用户权限** - **修改配置文件:** 更新Spring Security的配置文件,使其能够从数据库中读取用户信息和权限数据。 - **数据库表结构:** 设计并创建数据库表来存储用户信息和权限数据。 ...

    spring security 参考手册中文版

    第七部分 Spring数据集成 273 38. Spring Data&Spring安全配置 273 39. @Query中的安全表达式 273 第八部分 附录 274 40.安全数据库模式 274 40.1用户模式 274 40.1.1集团当局 274 40.2持久登录(记得我)架构 275 ...

    spring security4架包

    综上所述,这个"spring security4架包"涵盖了Spring Security的各个方面,从Web安全、用户认证、权限控制到测试支持和第三方服务集成,为构建安全的Java Web应用提供了全面的工具集。使用这些组件,开发者可以构建出...

    spring-security-2.0.5.jar2

    Spring Security是Spring生态系统的组成部分,主要负责应用程序的安全性,包括用户认证、权限控制和会话管理等。2.0.5版本虽已较为古老,但它的设计理念和核心机制对于理解现代版本仍有重要价值。 二、认证机制 1. ...

    spring-security-2.0.4.zip

    随着项目的成熟和社区的发展,Acegi被SpringSource(现在是Pivotal Software的一部分)正式接纳并重命名为Spring Security,以更好地融入Spring生态系统,并保持与Spring的紧密集成。 Spring Security的核心功能...

    spring security安全框架学习

    - Spring Security 3支持与其他身份验证服务集成,如OAuth用于API保护,OpenID用于第三方登录。 在"spring_security.sql"文件中,可能包含了创建上述数据库表的SQL脚本,用于演示Spring Security如何与数据库配合...

    spring-security3.1.4 完整的jar包

    3. **spring-security-config-3.1.4.RELEASE.jar**:配置模块允许开发者使用XML或注解来定义安全规则,如访问控制、角色分配等。它包含了表达式语言,使得在定义访问控制时可以使用自定义逻辑。 4. **spring-...

    spring 3 security

    Spring Security 3提供内置的CSRF防护机制,防止恶意第三方在用户浏览器中伪造请求。 7. **Web Expression Configuration** 在Spring Security 3中,可以通过XML或Java配置来定义安全规则,使用表达式来定义访问...

    SpringSecurit安全权限管手册

    2. **第二章:自定义数据库表结构** 在实际应用中,SpringSecurity的默认用户存储可能不符合需求。这一章会讲解如何自定义用户信息存储,比如使用自定义的UserDetailsService和JDBC用户存储,以便将用户信息存储在...

    2013-ProSpringSecurity

    ### 第2章:介绍Spring Security 这一章深入介绍了Spring Security框架的基础知识,包括其历史背景、设计理念以及与Spring框架之间的集成方式。通过本章的学习,读者能够理解Spring Security如何解决常见的安全性...

    Spring-Security:Spring安全课程

    6. **CSRF(跨站请求伪造)防护**:默认情况下,Spring Security启用CSRF防护,防止恶意第三方在用户浏览器上模拟合法的POST请求。 7. **Web安全配置**:Spring Security通过`WebSecurityConfigurerAdapter`抽象类...

Global site tag (gtag.js) - Google Analytics