在认识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》):
无论是保护WEB资源还是保护业务方法或者领域对象,Spring Security都的通过上图中的组件来完成的。本文主要阐述如何使用Spring Security对WEB应用程序的资源进行安全访问控制,并通过一个简单的实例来对Spring Security提供的各种过滤器的功能和配置方法进行描述。
二 保护Web资源
Spring Security提供了很多的过滤器,它们拦截Servlet请求,并将这些请求转交给认证处理过滤器和访问决策过滤器进行处理,并强制安全性,认证用户身份和用户权限以达到保护Web资源的目的。对于Web资源我们大约可以只用6个过滤器来保护我们的应用系统,下表列出了这些安全过滤器的名称作用以及它们在系统中的执行顺序:
接下来,通过一个实例来说明它们的具体使用方法和如何在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 配置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>
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(提供者管理器)自己并不实现身份验证,而是把这项工作交给了多个认证提供者(提供者集合)或者说的多个认证来源。
【下载地址】
百度网盘链接:https://pan.baidu.com/s/1pX-2QJqaOg0u0b6YEvdr1A
提取码:jnip
相关文章
使用-JFreeChart来创建基于web的图表
XStream使用文档
WebService发布过程及常见问题
webpack实战入门进阶调优分享
weblogic调优参数及监控指标
weblogic节点管理
weblogic管理控制台概述
weblogic-部署和启动
WebLogic-Server-性能及调优-调优-Java-虚拟机
Java 虚拟机(Java virtual machine,简称 JVM)是一种虚拟“执行引擎”实例,可在微处理器上执行 Java 类文件中的字节码。调整 JVM 的方式会影响 Weblogic Server 和应用程序的性能。
Velocity是一个基于java的模板引擎(template engine)。它允许任何人仅仅简单的使用模板语言(template language)来引用由java代码定义的对象。
Velocity 用户手册是帮助页面设计者和内容提供者认识 Velocity 和其简单而功能强大的脚本语言――Velocity 模板语言(VTL)。在手册上的许多例子,都是用 Velocity 插入动态的内容到网页上,但是所有的 VLT 例子都能应用到其他的页面和模板中。
FlashFXP绿色版网盘下载,附激活教程 1764
FlashFxp百度网盘下载链接:https://pan.baidu.com/s/1MBQ5gkZY1TCFY8A7fnZCfQ。FlashFxp是功能强大的FTP工具
Adobe Fireworks CS6 Ansifa绿色精简版网盘下载 1553
firework可以制作精美或是可以闪瞎眼的gif,这在广告领域是需要常用的,还有firework制作下logo,一些原创的图片还是很便捷的,而且fireworks用法简单,配合dw在做网站这一块往往会发挥出很强大的效果。百度网盘下载链接:https://pan.baidu.com/s/1fzIZszfy8VX6VzQBM_bdZQ
navicat for mysql中文绿色版网盘下载 1616
Navicat for Mysql是用于Mysql数据库管理的一款图形化管理软件,非常的便捷和好用,可以方便的增删改查数据库、数据表、字段、支持mysql命令,视图等等。百度网盘下载链接:https://pan.baidu.com/s/1T_tlgxzdQLtDr9TzptoWQw 提取码:y2yq
火车头采集器(旗舰版)绿色版网盘下载 1701
火车头采集器是站长常用的工具,相比于八爪鱼,简洁好用,易于配置。火车头能够轻松的抓取网页内容,并通过自带的工具对内容进行处理。站长圈想要做网站,火车头采集器是必不可少的。百度网盘链接:https://pan.baidu.com/s/1u8wUqS901HgOmucMBBOvEA
Photoshop(CS-2015-2023)绿色中文版软件下载 1816
安装文件清单(共46G)包含Window和Mac OS各个版本的安装包,从cs到cc,从绿色版到破解版,从安装文件激活工具,应有尽有,一次性打包。 Photoshop CC绿色精简版 Photoshop CS6 Mac版 Photoshop CC 2015 32位 Photoshop CC 2015 64位 Photoshop CC 2015 MAC版 Photoshop CC 2017 64位 Adobe Photoshop CC 2018 Adobe_Photoshop_CC_2018 Photoshop CC 2018 Win32 Photoshop CC 2018 Win64