在最后一章中,我们将会了解从Spring Security2迁移到Spring Security3时常见问题的相关情况。
在本章中,我们将会:
l 了解Spring Security 3的重要增强;
l 理解已有的Spring Security 2应用迁移到Spring Security 3时所需要的配置修改;
l 阐述Spring Security 3中重要类和包的移动。
一旦你学完本章的内容,你将会很熟悉怎样将Spring Security 2应用迁移到Spring Security 3上。
你可能计划将现存的Spring Security 2应用迁移到Spring Security 3,或者试图为Spring Security 2应用添加功能并想在本书中寻找一些参考。我们将会在本章中尽可能解决你所关注的这两个问题。
首先,我们将会了解Spring Security 2和Spring Security 3的重要区别——包括功能和配置。其次,我们将会对配置匹配和类名变化提供一些参考。你可以将本书中的例子从Spring Security 3转换到Spring Security 2(这是可行的)。
一个重要的迁移注意事项是Spring Security 3需要Spring框架3和Java5(1.5)或更高。注意的是,在很多情况下,迁移其它的组件比升级Spring Security会对你的应用产生更大的影响。
Spring Security 3比Spring Security 2有了很重要的增强,包括:
l 增加了Spring表达式语言(Spring Expression Language,SpEL)对访问声明的支持,包括URL和方法访问声明,我们在第二章:Spring Security起步和第五章:精确的访问控制中已经介绍了;
l 添加了对认证和访问成功及失败添加了精确的配置,我们在第二章,第五章进行了简单介绍,而在第六章:高级配置和扩展中进行了详细介绍;
l 增强的方法访问声明,包括基于注解的调用事先和事后访问检查和过滤,以及security命名空间配置对自定义bean行为的良好支持。这些功能我们在第五章中进行了介绍;
l 使用security命名空间对session访问和并发控制进行精确管理,这些在第六章中进行了介绍;
l 值得一提的是ACL模块,移除了o.s.s.acl中的遗留代码并解决了ACL框架中一些重要问题。ACL的配置和支持在第七章:访问控制列表中进行了介绍;
l 支持OpenID属性交换,以及对OpenID健壮性的其它增强,这在第八章:对OpenID开放中进行了介绍;
l 通过Spring Security Extension项目对Kerberos和SAML提供了新的支持,这些我们在第十二章:Spring Security扩展中进行了讨论。
其它重要的良好变化包括对代码和框架的配置进行了重构和清理,所以整体结构和用法都有所变化。Spring Security的作者努力增加以前所没有的可扩展性,尤其是在登录和URL重定向方面。
如果你已经在Spring Security2环境下工作,如果不是遇到该框架功能的边界你可能找不到强制升级的理由。但是,如果你发现Spring Security2在可用扩展点、代码结构或可配置性方面的限制,欢迎阅读我们在本章剩余部分详细讲到的细微变化。
Spring Security 3的很多变化在security命名空间风格的配置。尽管本章不能详细涵盖所有的细微变化,但是我们尽力包含迁移至Spring Security3时会影响到你的变化。
AuthenticationManager配置的重新组织
Spring Security 3最重要的变化在于AuthenticationManager的配置和AuthenticationProvider相关的元素。在Spring Security 2中,AuthenticationManager和AuthenticationProvider的配置是完全不相关的——声明一个AuthenticationProvider不需要任何AuthenticationManager的概念。
<authentication-provider> <jdbc-user-service data-source-ref="dataSource"/> </authentication-provider>
在Spring Security 2中,声明<authentication-manager>元素是作为AuthenticationProvider的兄弟节点的。
<authentication-manager alias="authManager"/> <authentication-provider> <jdbc-user-service data-source-ref="dataSource"/> </authentication-provider> <ldap-authentication-provider server-ref="ldap://localhost:10389/"/>
在Spring Security 3中,所有的AuthenticationProvider元素必须是<authentication-manager>的子节点,所以应该重写为如下格式:
<authentication-manager alias="authManager"> <authentication-provider> <jdbc-user-service data-source-ref="dataSource"/> </authentication-provider> <ldap-authentication-provider server-ref= "ldap://localhost:10389/"/> </authentication-manager>
当然这意味着现在<authentication-manager>元素需要在任何security命名空间配置中都要存在。
在Spring Security 2中,如果你有自定义的AuthenticationProvider,你应该在其bean声明中用<custom-authentication-provider>元素来进行包装,例如,我们在第六章中实现的自定义AuthenticationProvider:
<bean id="signedRequestAuthenticationProvider" class="com.packtpub.springsecurity.security .SignedUsernamePasswordAuthenticationProvider"> <security:custom-authentication-provider/> <property name="userDetailsService" ref="userDetailsService"/> <!-- ... --> </bean>
但是将这个自定义AuthenticationProvider迁移到Spring Security 3时,我们需要移除包装元素并使用<authentication-provider>元素的ref属性来配置AuthenticationProvider,就像我们在第三章中所看到的,如下:
<authentication-manager alias="authenticationManager"> <authentication-provider ref= "signedRequestAuthenticationProvider"/> </authentication-manager>
当然,自定义provider的源码会因为Spring Security 3的类更换位置和改名而有所变化——在本章后面会有基本介绍而在本章的源码中会有更为细节的匹配关系。
Session管理选项的新配置语法
除了继续支持框架前面版本的session固化和并发控制功能,Spring Security 3为自定义URL以及session和并发控制功能相关的类添加了新的配置功能,我们在第六章中进行了详细介绍。如果你的旧应用配置了session固化和并发session控制,这些配置有了新的位置,即在<http>中的<session-management>指令中。
在Spring Security 2中,这些选项将会配置如下:
<http ... session-fixation-protection="none"> <!-- ... --> <concurrent-session-control exception-if-maximum-exceeded="true" max-sessions="1"/> </http>
在Spring Security 3的配置语法中,从<http>元素中移除了session-fixation-protection属性,配置如下:
<http ...> <session-management session-fixation-protection="none"> <concurrency-control error-if-maximum-exceeded="true" max-sessions="1"/> </session-management> </http>
你可以看到,这些选项的新的逻辑组织更为合理并为进一步的扩展留下了空间。
自定义过滤器配置的变化
很多的Spring Security 2用户开发过自定义的认证过滤器(或其它过滤器来改变安全请求的流程)。如同自定义的认证provider,以前这些过滤器也是通过带有<custom-filter>元素的bean来声明的。这使得在一些场景下将过滤器直接配置到Spring Security配置中有点困难。
在Spring Security 2的环境下,让我们看一下第六章中签名请求头过滤器的配置示例。
<bean id="requestHeaderFilter" class="com.packtpub .springsecurity.security.RequestHeaderProcessingFilter"> <security:custom-filter after="AUTHENTICATION_PROCESSING_FILTER"/> <property name="authenticationManager" ref="authenticationManager"/> </bean>
将其与Spring Security 3相同的配置进行对比,你可以看到bean的声明和安全织入是独立完成的。自定义的过滤器在<http>元素中声明,如下:
<http ...> <!-- ... --> <custom-filter ref="requestHeaderFilter" before="FORM_LOGIN_FILTER"/> <!-- ... --> </http>
尽管bean的声明与Spring Security 2保持相同,但是你可能会预料到,自定义过滤器的代码差别很大。我们在本章包含了过滤器的示例代码(使用Spring Security 2),为你了解自定义过滤器在转换成Spring Security 3之前和之后是什么样子提供指导。
另外,一些过滤器的逻辑名在Spring Security 3中发生了变化。我们在下面提供了一个变化列表而在附录:参考材料中提供了完整的列表。
Spring Security 2 | Spring Security 3 |
SESSION_CONTEXT_INTEGRATION_FILTER | SECURITY_CONTEXT_FILTER |
CAS_PROCESSING_FILTER | CAS_FILTER |
AUTHENTICATION_PROCESSING_FILTER | FORM_LOGIN_FILTER |
OPENID_PROCESSING_FILTER | OPENID_FILTER |
BASIC_PROCESSING_FILTER | BASIC_AUTH_FILTER |
NTLM_FILTER | 在Spring Security中移除了 |
你在定位<custom-filter>元素时,在你的配置文件中必须进行这些修改。
CustomAfterInvocationProvider的变化
Spring Security 2中的最后一个bean包装被直接、内联的元素声明所取代了,这就是<custom-after-invocation-provider>元素声明的CustomAfterInvocationProvider。
<bean id="customAfterInvocationProvider" class="com.packtpub.springsecurity.security .CustomAfterInvocationProvider"> <security:custom-after-invocation-provider/> </bean>
类似于我们在前面看到其它Spring Security 2 bean包装,在Spring Security 3中,这个元素被移到<global-method-security>声明中,只会有一个简单的bean引用。
<global-method-security ...> <after-invocation-provider ref="customAfterInvocationProvider"/> </global-method-security>
我们已经在第五章中介绍了方法安全的各个方面,包括在Spring Security 3中新增的一些关于方法安全的有趣选项。
小的配置变化
以下简单介绍了Spring Security 2 和3之间的其它配置属性变化:
l 在Spring Security 3中使用auto-config属性,将不会默认配置remember me服务。你需要在<http>元素中明确添加<remember-me>声明;
l 对于LDAP配置,在Spring Security 3中group-search-base-attribute的默认值(用来进行LDAP权限查找)从ou=Groups变成了空字符串(LDAP的根)。我们在第九章:LDAP目录服务中用过该属性;
l 在Spring Security 3中,用来手动配置过滤器链的<filter-invocation-definition-source>包装元素被重命名为<filter-security-metadata-source>。我们在第六章使用明确bean配置的时候用过这种类型的设置;
l 在Spring Security 3中,<concurrent-session-control>元素相关的exception-if-maximum-exceeded属性被移到并重命名为<concurrency-control>元素的error-if-maximum-exceeded属性;
l 在Spring Security 3中,当使用内存DAO UserDetailsService在配置文件中声明用户时,password属性不再是必须的;
l 内置的NTLM认证支持已经在Spring Security 3中移除了,而是用Kerberos认证进行了替换(请查阅第十二章了解配置Kerberos的细节)。这是升级用户比较关注的事情,而在Spring Security社区中有一些活动想让Spring Security 3支持NTLM。也许在本书出版的时候,可能会有一个Spring Security扩展项目支持Spring Security 3中的NTLM。
Spring Security 3中剩余的security命名空间XML配置语法变化为功能的增加,并不会对已有应用带来迁移的问题。
尽管在比较简单的Spring Security 2应用中,类在包中的位置关系不大,但是大多数的Spring Security应用不会与底层的代码无关。所以,我们感觉为你指出Spring Security 2 和3之间的总体的包迁移和类重命名会有所用处。
不管在什么地方,我们都试图尽可能精确的匹配类——在这里我们提供了整体的主要包迁移,并且(如果你需要)更复杂的列表可以随源码一起下载。下表展现了Spring Security 2到Spring Security 3最大的类位置变更——我们已经压缩了这个表以使其包含大多数的你可能希望看到的变化:
类的数量 | Spring 2中的位置 | Spring 3中的位置 |
13 | o.s.s | o.s.s.authentication |
13 | o.s.s.acls | o.s.s.acls.model |
13 | o.s.s.event.authentication | o.s.s.authentication.event |
12 | o.s.s.vote | o.s.s.access.vote |
11 | o.s.s.ui.rememberme | o.s.s.web.authentication.rememberme |
10 | o.s.s.providers.jaas | o.s.s.authentication.jaas |
10 | o.s.s.securechannel | o.s.s.web.access.channel |
10 | o.s.s.userdetails.ldap | o.s.s.ldap.userdetails |
9 | o.s.s.providers.encoding | o.s.s.authentication.encoding |
8 | o.s.s.config | o.s.s.config.authentication |
8 | o.s.s.util | o.s.s.web.util |
7 | o.s.s.config | o.s.s.config.http |
7 | o.s.s.context | o.s.s.core.context |
7 | o.s.s.userdetails | o.s.s.core.userdetails |
6 | o.s.s | o.s.s.access |
6 | o.s.s.afterinvocation | o.s.s.acls.afterinvocation |
6 | o.s.s.event.authorization | o.s.s.access.event |
6 | o.s.s.util | o.s.s.web |
5 | o.s.s.annotation | o.s.s.access.annotation |
5 | o.s.s.authoritymapping | o.s.s.core.authority.mapping |
5 | o.s.s.providers | o.s.s.authentication |
5 | o.s.s.token | o.s.s.core.token |
5 | o.s.s.ui | o.s.s.web.authentication |
如果你发现类移动相当大,你是正确的!在Spring Security 3包的重新组织中,很少有类不被接触到。希望这个整体的介绍能够在你寻找类的时候为你指明方向。再一次强调,请查询本章的下载内容来了解更详细的类和类之间的匹配。
对整个框架重新组织的好处在于现在更加模块化,并将JAR文件分割为特定功能的元素,介绍如下(我们使用nnn待代替释放版本号):
JAR名 | 功能 |
spring-security-acl-nnn.jar | 支持ACL(见第七章) |
spring-security-cas-client-nnn.jar | 支持CAS(见第十章) |
spring-security-config-nnn.jar | 整体配置支持 |
spring-security-core-nnn.jar | 核心框架和类 |
spring-security-ldap-nnn.jar | 支持LDAP(见第九章) |
spring-security-openid-nnn.jar | 支持OpenID(见第八章) |
spring-security-taglibs-nnn.jar | 支持JSP标签库(见第三、五、七章) |
spring-security-web-nnn.jar | 支持web层 |
模块化意味着,例如,可以部署Spring Security到一个非web的应用而不需要任何web相关的依赖(spring-security-config和spring-security-core可能足够满足你的需求)。
本章中我们了解了将已有的Spring Security 2项目升级到Spring Security 3会遇到的大小变化。在本章中,我们:
l 了解了我们将要升级的框架所拥有的明显功能增强;
l 学习了可能阻碍升级的需求、依赖以及常见的代码和配置变化;
l 调查了(整体上)Spring Security的作者在代码重构时代码重新组织的变化。
如果这是你阅读的第一章,我们希望你能转向本书的其它部分,将本章作为平滑升级到Spring Security 3的一个指导。