在认识Spring
Security
之前,所有的权限验证逻辑都混杂在业务逻辑中,用户的每个操作以前可能都需要对用户是否有进行该项操作的权限进行判断,来达到认证授权的目的。类似这样的权限验证逻辑代码被分散在系统的许多地方,难以维护。AOP(Aspect Oriented Programming)
和Spring
Security为我们的应用程序很好的解决了此类问题,正如系统日志,事务管理等这些系统级的服务一样,我们应该将它作为系统一个单独的”切面
”进行管理,以达到业务逻辑与系统级的服务真正分离的目的,Spring
Security将系统的安全逻辑从业务中分离出来。
本文代码运行环境:
JDK6.0
spring-framework-2.5.4
spring-security-2.0.0
JavaEE5
Web
容器:
Apache
Tomcat6.0
IDE
工具:
Eclipse3.3+MyEclipse6.5
操作系统:
Linux(Fedora
8)
这只是我个人的学习总结而已,还请高手们指出本文的不足之处。
一 Spring
Security 简介
这里提到的Spring Security也就是被大家广为熟悉的Acegi Security
,2007年底Acegi Security正式成为Spring Portfolio
项目,并更名为Spring Security。Spring
Security
是一个能
够为
基于Spring的企业
应
用系
统
提供描述性安全访问控制解决方案的安全框架。它提供了一
组
可以在Spring
应
用上下文中配置的Bean,充分利用了Spring IoC(依
赖
注入,也称控制反转)和AOP(面向切面
编
程)
功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。
通过在许多项目中实践应用以及社区的贡献,如今的
Spring Security
已经成为Spring Framework
下最成熟的安全系统,它为我们提供了强大而灵活的企业级安全服务,如:
Ø
认证授权机制
Ø
Web
资源访问控制
Ø
业务方法调用访问控制
Ø
领域对象访问控制
Access Control List
(ACL
)
Ø
单点登录(
Central Authentication Service
)
Ø
X509
认证
Ø
信道安全(
Channel Security
)管理等功能
当保护Web资源时,Spring Security
使用Servlet
过滤器
来拦截
Http
请求进行身份验证并强制安全性,以确保WEB资源被安全的访问。如下图是Spring
Security的主要组件图(摘自《Spring in
Action
》):
图
1 Spring Security的基本组件
无论是保护
WEB资源还是保护业务方法或者领域对象,
Spring Security
都的通过上图中的组件来完成的。本文主要阐述如何使用Spring
Security对WEB应用程序的资源进行安全访问控制,并通过一个简单的实例来对Spring
Security提供的各种过滤器的功能和配置方法进行描述。
二 保护Web资源
Spring
Security
提供了很多的过滤器,它们拦截Servlet请求,并将这些请求转交给认证处理过滤器和访问决策过滤器进行处理,并强制安全性,认证用户身份和用户权限以达到保护Web资源的目的。对于Web资源我们大约可以只用6个
过滤器来保护我们的应用系统,下表列出了这些安全过滤器的名称作用以及它们在系统中的执行顺序:
过
滤
器
|
作
用
|
通道处理过滤器
|
确保请求是在安全通道(HTTP和HTTPS)之上传输的
|
认证处理过滤器
|
接受认证请求,并将它们转交给认证管理器进行身份验证
|
CAS
处理过滤器
|
接受CAS服务票据,验证Yale
CAS(单点登录)是否已经对用户进行了认证
|
HTTP
基本授权过滤器
|
处理使用HTTP基本认证的身份验证请求
|
集成过滤器
|
处理认证信息在请求间的存储(比如在HTTP会话中)
|
安全强制过滤器
|
确保用户己经认证,并且满足访问一个受保护Web资源的权限需求
|
接下来,通过一个实例来说明它们的具体使用方法和如何在Spring中进行配置。
1
建立Spring
Security项目
首先在
MyEclipse中创建一个
Web Project,并使用
MyEclipse工具导入
Spring项目的依赖
JAR包,并生成默认的,这里暂时不会用到这个文件,本文只是通过一个简单的实例来说明如何配置使用
Spring
Security,不会涉及到数据库,而是使用一个用户属性(
users.properties)文件来保存用户信息(包括用户名,密码及相应的权限),但在实际的项目中,我们很少会这样做,而是应该把用户信息存在数据库中,下一篇文章中将会详细介绍并用到这个文件来配置
Hibernate,这里我们保留它。
现在还需要为项目导入
Spring Security的
JAR包,它没有包括在
Spring
Framework
中,你可以从http://www.springframework.org/download/
下载,并将spring-security-core-2.0.0.jar
(这是核心代码库)和spring-security-core-tiger-2.0.0.jar
(和annotation有关的,比如使用注解对方法进行安全访问控制,在下一篇中会用到)拷贝到项目的lib目录下,其中也包括两个实例(tutorial和contacts),并且两个实例中都包括了如何使用Spring
2.0的命名空间
来配置Spring Security,无论你对
Spring
2.0
命名空间的使用是否了解,它将使我们的配置文件大大缩短,简化开发,提高生产效率。
到此,我们的
Spring Security项目就建好了,项目目录结构如下图所示:
图
2 项目目录结构
2 配置
web.xml
Spring Security使用一组过滤器链来对用户进行身份验证和授权。首先,在
web.xml文件中添加
FilterToBeanProxy
过滤器配置:
<!----> 1
<
filter
>
2 <
filter-name
>
springSecurityFilterChain
</
filter-name
>
3
<
filter-class
>
4
org.springframework.security.util.FilterToBeanProxy
5
</
filter-class
>
6
<
init-param
>
7 <
param-name
>
targetClass
</
param-name
>
8
<
param-value
>
9
org.springframework.security.util.FilterChainProxy
10
</
param-value
>
11
</
init-param
>
12
</
filter
>
13
org.springframework.security.util.
FilterToBeanProxy
实现了Filter接口,它通过调用
WebapplicationContextUtils
类的getWebApplicationnContext(servletContext)
方法来获取
Spring的应用上下文句柄,并通过
getBean(beanName)方法来获取
Spring受管
Bean的对象,即这里
targetClass
参数
配置的
Bean,并通过调用
FilterChain
Proxy
的
init()
方法来启动
Spring
Security
过滤器链进行各种身份验证和授权服务(
FilterChainProxy
类也是实现了
Filter
接口),
从而将过滤功能委托给Spring的
FilterChainProxy
受管Bean(
它维护着一个处理验证和授权的过滤器列表,列表中的过滤器按照一定的顺序执行并完成认证过程
),这样即简化了web.xml文件的配置,又能充分利用
Spring的IoC功能来完成这些过滤器执行所需要的其它资源的注入。
当用户发出请求,过滤器需要根据
web.xml
配置的请求映射地址来拦截用户请求,这时
Spring Security开始工作,它会验证你的身份以及当前请求的资源是否与你拥有的权限相符,从而达到保护
Web资源的功能,下面是本例所要过滤的用户请求地址:
<!----> 1
<
filter-mapping
>
2
3
<
filter-name
>
springSecurityFilterChain
</
filter-name
>
4
5
<
url-pattern
>
/j_spring_security_check
</
url-pattern
>
6
7
</
filter-mapping
>
8
9
<
filter-mapping
>
10
11
<
filter-name
>
springSecurityFilterChain
</
filter-name
>
12
13
<
url-pattern
>
/*
</
url-pattern
>
14
15
</
filter-mapping
>
提示:
/j_spring_security_check是Spring
Security默认的进行表单验证的过滤地址,你也可以修改为别的名称,但是需要和
applicationContext-security.xml中相对应,当然还会涉及到其它一些默认值(可能是一个成员变量,也可能是别的请
求地址),在下文我们将看到,建议你在阅读此文的同时,应该参照Spring
Security项目的源代码,便于你更好的理解。
|
|
3
配置applicationContext-security.xml
3.1
FilterChainProxy
过滤器链
FilterChainProxy
会按顺序来调用一组filter,使这些filter即能完成验证授权的本质工作,又能享用Spring Ioc的功能来方便的得到其它依赖的资源。FilterChainProxy配置如下:
<!----> 1
<
bean
id
="filterChainProxy"
class
="org.springframework.security.util.FilterChainProxy"
>
2
<
property
name
="filterInvocationDefinitionSource"
>
3
<
value
>
<![CDATA[
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
4
PATTERN_TYPE_APACHE_ANT
/**=httpSessionContextIntegrationFilter,logoutFilter,
5
authenticationProcessingFilter,securityContextHolderAwareRequestFilter,
6
rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,
7
filterSecurityInterceptor
8
]]>
</
value
>
9
</
property
>
10
</
bean
>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
定义
URL在匹配之前必须先转为小写,
PATTERN_TYPE_APACHE_ANT 定义了使用
Apache
ant
的匹配模式,/**
定义的将等号后面的过滤器应用在那些
URL上,这里使用全部
URL过滤,每个过滤器之间都适用逗号分隔,它们按照一定的顺序排列。
提示:
特别需要注意的是,即使你配置了系统提供的所有过滤器,这个过滤器链会很长,但是千万不要使用换行,否则它们不会正常工作,
容器甚至不能正常启动。
|
|
下面根据
FilterChainProxy
的配置来介绍各个过滤器的配置,各个过滤器的执行顺序如以上配置。
首先是
通道处理过滤器
,如果你需要使用HTTPS,这里我们就使用HTTP进行传输,所以不需要配置通道处理过滤器,然后是集成过滤器,配置如下:
<!---->1
<
bean
id
="httpSessionContextIntegrationFilter"
2
3
class
="org.springframework.security.context.HttpSessionContextIntegrationFilter"
/>
httpSessionContextIntegrationFilter
是
集成过滤器的一个实现,在用户的一个请求过程中,用户的认证信息通过SecurityContextHolder
(使用ThreadLoacl
实现)进行传递的,所有的过滤器都是通过SecurityContextHolder来获取用户的认证信息,从而在一次请求中所有过滤器都能共享Authentication
(认证),减少了HttpRequest参数的传送,下面的代码是从安全上下文的获取Authentication对象的方法:
<!---->1
SecurityContext context
=
SecurityContextHolder.getContext();
2
3
Authentication authentication
=
context.getAuthentication();
但是,ThreadLoacl不能跨越多个请求存在,所以,集成过滤器在请求开始时从Http会话中取出用户认证信息并创建一个SecurityContextHolder将Authentication对象保存在其中,在请求结束之后,在从SecurityContextHolder中获取Authentication对象并将其放回Http会话中,共下次请求使用,从而达到了跨越多个请求的目的。集成过滤器还有其它的实现,可以参考相关文档。
logoutFilter
(退出过滤器) ,退出登录操作:
<!----> 1
<
bean
id
="logoutFilter"
2
3
class
="org.springframework.security.ui.logout.LogoutFilter"
>
4
5
<
constructor-arg
value
="/index.jsp"
/>
6
7
<
constructor-arg
>
8
9
<
list
>
10
11
<!--
实现了LogoutHandler接口(logout方法)
-->
12
13
<
ref
bean
="rememberMeServices"
/>
14
15
<
bean
class
="org.springframework.security.ui.logout.SecurityContextLogoutHandler"
/>
16
17
</
list
>
18
19
</
constructor-arg
>
20
21
</
bean
>
LogoutFilter
的构造函数需要两个参数,第一个是退出系统后系统跳转到的URL,第二个是一个LogoutHandler类型的数组,这个数组里的对象都实现了LogoutHandler接口,并实现了它的logout方法,用户在发送退出请求后,会一次执行LogoutHandler
数组的对象并调用它们的 logout方法
进行一些后续的清理操作,主要是从SecurityContextHolder对象中清楚所有用户的认证信息(Authentication对象),将用户的会话对象设为无效,这些都时由SecurityContextLogoutHandler来完成。LogoutFilter还会清除Cookie记录,它由另外一个Bean来完成(RememberMeServices
)。
<ref
bean="rememberMeServices"/>
标记指向了我们另外配置的一个Bean:
<!---->1
<
bean
id
="rememberMeServices"
class
="org.springframework.security.ui.rememberme.TokenBasedRememberMeServices"
2
p:key
="springsecurity"
3
p:userDetailsService-ref
="userDetailsService"
/>
TokenBasedRememberMeServices
继承自系统的AbstractRememberMeServices
抽象类(实现了RememberMeServices和
LogoutHandler两个接口), RememberMeServices接口的loginSuccess方法
负责在用户成功登录之后将用户的认证信息存入Cookie中,这个类在后续的过滤器执行过程中也会被用到。
另一个userDetailsService
属性也是指向了我们配置的Bean,
它负责从数据库中读取用户的信息,这个类的详细配置将在后面的部分详细介绍,这里只是简单的认识一下。
过滤器链的下个配置的过滤器是authenticationProcessingFilter(认证过程过滤器)
,我们使用它来处理表单认证,
当接受到与
filterProcessesUrl
所定义相同的请求时
它开始工作
:
<!----> 1
<
bean
id
="authenticationProcessingFilter"
2
3
class
="org.springframework.security.ui.webapp.AuthenticationProcessingFilter"
4
5
p:authenticationManager-ref
="authenticationManager"
6
p:authenticationFailureUrl
="/login.jsp?login_error=1"
7
p:defaultTargetUrl
="/default.jsp"
8
p:filterProcessesUrl
="/j_spring_security_check"
9
p:rememberMeServices-ref
="rememberMeServices"
/>
下面列出了认证过程过滤器配置中各个属性的功能:
1.authenticationManager
认证管理器
2.authenticationFailureUrl
定义登录失败时转向的页面
3.defaultTargetUrl
定义登录成功时转向的页面
4.filterProcessesUrl
定义登录请求的地址(在web.xml中配置过)
5.rememberMeServices
在验证成功后添加cookie信息
这里也用到了rememberMeServices,如果用户认证成功,将调用RememberMeServices的loginSuccess方法
将用户认证信息写入Cookie中,这里也可以看到使用IoC的好处。
决定用户是否有权限访问受保护资源的第一步就是要确定用户的身份,最常用的方式就是用户提供一个用户名和密码以确认用户的身份是否合法,这一步就是由认证过程过滤器调用authenticationManager(认证管理器)来完成的。org.springframework.security.AuthenticationManager
接口定义了一个authenticate方法
,它使用Authentication作为入口参数(只包含用户名和密码),并在验证成功后返回一个完整的Authentication对象(包含用户的权限信息GrantedAuthority
数组对象),authenticationProcessingFilter(认证过程过滤器)会将这个完整的Authentication对象存入SecurityContext
中,
如果认证失败
会抛出一个AuthenticationException并
跳转到authenticationFailureUrl
定义的URL。认证管理其配置如下:
<!----> 1
<
bean
id
="authenticationManager"
2
3
class
="org.springframework.security.providers.ProviderManager"
4
p:sessionController-ref
="concurrentSessionController"
>
5
<
property
name
="providers"
>
6
<
list
>
7
<
ref
bean
="daoAuthenticationProvider"
/>
8
<
bean
9
10
class
="org.springframework.security.providers.anonymous.AnonymousAuthenticationProvider"
11
p:key
="springsecurity"
/>
12
<
bean
13
14
class
="org.springframework.security.providers.rememberme.RememberMeAuthenticationProvider"
15
p:key
="springsecurity"
/>
16
</
list
>
17
</
property
>
18
</
bean
>
正如在配置中看到的一样,系统使用org.springframework.security.providers.ProviderManager
(提供者管理器)
类作为认证管理器
的一个实现,事实上这个类是继承自实现了AuthenticationManager
接口的
AbstractAuthenticationManager类。需要注意的是ProviderManager
(提供者管理器)
自己并不实现身份验证,而是把这项工作交给了多个认证提供者(提供者集合)或者说的多个认证来源。
分享到:
相关推荐
"springsecurity-namespace"可能指的是Spring Security的XML命名空间配置。在Spring Security的早期版本中,使用XML配置是最常见的实践。例如,你可能会看到以下片段: ```xml **" access="hasRole('ROLE_ADMIN')...
在“Spring Security学习总结2_2”中,我们可能涉及了对Spring Security更深入的探讨,特别是关于其核心概念和实际应用的细节。 首先,Spring Security的核心组件包括Security Context(安全上下文)、...
1. **Filter Security Interceptor**:这是SpringSecurity的主要过滤器,负责检查请求并决定是否允许访问。它会根据预定义的访问控制规则进行判断。 2. **Authentication Manager**:处理用户认证的组件,可以使用...
【Spring Security 学习总结】 Spring Security 是一个强大的和高度可定制的身份验证和访问控制框架,用于保护基于 Java 的应用程序。本学习总结文档主要针对初学者,旨在剖析一个不安全的应用程序并阐述如何通过 ...
SpringSecurity学习总结一.pdf
在"Spring Security学习总结一(补命名空间配置)"的文件中,可能涵盖了如何在Spring Security的XML配置中补充命名空间的步骤。命名空间的引入是为了简化配置,例如`<http>`元素用于配置安全拦截和访问规则,`...
总结来说,"REST-spring-security"项目展示了如何使用Spring Security来保护RESTful Web服务,包括身份验证、授权、访问控制和安全配置。这个项目可以帮助开发者理解如何在实际应用中实现安全的REST API,确保服务的...
### Spring Security 学习总结 #### 一、Spring Security 概述 Spring Security 是一个功能强大的安全框架,它为基于 Java 的应用程序提供了认证(authentication)和授权(authorization)功能。在 Spring ...
总结,Spring Security 3.1作为一款强大的安全框架,虽然版本较旧,但仍值得开发者深入研究。通过学习和实践,我们可以掌握如何构建安全的Web应用,并理解其背后的原理,为今后的安全开发打下坚实基础。
总结,Spring Security 3的源码分析是一个深度学习的过程,涵盖了安全领域的多个方面。通过理解其内部工作机制,开发者可以更好地利用这一强大的框架,为应用程序提供安全的保障。同时,源码分析也能帮助开发者解决...
### Spring Security 概述与应用实践 #### 一、引言 在当今互联网时代,网络安全问题日益凸显,尤其是Web应用程序的...同时,结合实际案例的学习,能够帮助我们更好地理解和掌握Spring Security的核心概念与使用技巧。
spring security 学习总结暑假的时候在学习了Spring安全并成功运用到了项目中。在实践中摸索出了一套结合JSON +智威汤逊(JSON网络令牌)+Spring引导+ Spring Security的技术的权限方案趁着国庆假期记录一下。 内容 ...
对于初学者,建议从官方文档或教程开始学习,逐步熟悉Spring Security的安装、配置和使用流程。 #### Security命名空间配置 Spring Security通过XML命名空间简化了安全相关的配置。这部分文档详细介绍了如何使用...
### Spring Security3中文教程知识点概览 #### 一、安全核心概念与起步 Spring Security是Spring框架中的一个重要组成部分,主要用于为Web应用提供安全防护。它不仅提供了强大的认证和授权功能,还支持各种加密...
总结起来,"springSecurityTest.zip"文件提供了一个完整的环境,让你可以动手实践Spring Security的基础用法。通过学习其中的代码、笔记和文档,你将理解Spring Security如何与Spring框架协同工作,如何设置认证和...