最近在应用Spring Security的时候,积累了一些心得,写出来希望能给需要的人一些启示,毕竟网上对于spring security的配置和应用不是很多,大多是一些介绍acegi应用老文章。希望大家提出宝贵意见。此文的相应设置适用于spring security2.x。
Spring Security相对于Acegi在配置上方便了很多,具体的参考文档在http://www.family168.com/tutorial/springsecurity/html/springsecurity.html 上有中文翻译。
至于Spring Security的具体配置和应该可以从downpour的http://www.iteye.com/topic/319965一岾中学习。
在此我想写的是有关于multiple login pages的情况。
参考文章:san586的http://ss3ex.iteye.com/blog/452307。
问题:
对于多登录界面,要求实现不同的用户,比如前台用户和后台用户,分别在以下情况中实现到不同页面的转向:
1.在未登录时,访问受限页面
2.在登录以后,转向到不同的默认页面,比如前台用户转向到个人中心主页,后台用户转向到后台管理页面的首页。
3.在登录失败时,导向到错误页面。
4.在注销登录时,不同的用户转向到不同的注销成功界面。
由于Spring Security的核心是基于Spring基础之上的各种过滤器组成的链,而且规定,这些过滤器的顺序不可更改,其中一些元素自己使用而创建出的过滤器如HttpSessionContextIntegrationFilter, ExceptionTranslationFilter 或 FilterSecurityIntercepto 是不允许替换成自己所定义的过滤器的。
我们可以把自己的过滤器添加到队列中,使用custom-filter元素,使用这些名字中的一个,来指定自定义过滤器应该出现的位置:
<beans:bean id="myFilter" class="com.mycompany.MySpecialAuthenticationFilter"> <custom-filter position="AUTHENTICATION_PROCESSING_FILTER"/> </beans:bean>
position属性可以有before,position(对原来的过滤器进行替换),after等,后面的位置表示过滤器的位置。
在针对以上多登录界面的情况中的几个问题,downpour的一贴中给出了一种解决方案,是通过将session中设定标识,然后把转发的目标设定为action,在action中根据请求中的标识来进行发送到相应的页面。除了这种方法之外,跟据spring security的实现机理,我们完全可以通过实现自己的过滤器对来自不同用户的请求进行相应处理。
在进行表单认证的时候,AuthenticationProcessingFilter是验证执行机制的过滤器,通过对其的继承可以实现自定义的处理过程,出于减少编码量的考虑,我们可以在验证时配置两个AuthenticationProcessingFilter的实例,分别设置不同的filterprocessedurl来响应不同的请求,例如
<!-- 验证前台用户 --> <bean id="preLoginFilter" class="org.springframework.security.ui.webapp.AuthenticationProcessingFilter"> <sec:custom-filter before="AUTHENTICATION_PROCESSING_FILTER" /> <property name="authenticationManager" ref="authenticationManager" /> <property name="authenticationFailureUrl" value="/Seeworld/html" /> <property name="defaultTargetUrl" value="/" /> <property name="alwaysUseDefaultTargetUrl" value="true" /> <property name="filterProcessesUrl" value="/j_spring_security_check" /> </bean> <!-- 验证后台用户 --> <bean id="adminLoginFilter" class="org.springframework.security.ui.webapp.AuthenticationProcessingFilter"> <sec:custom-filter position="AUTHENTICATION_PROCESSING_FILTER" /> <property name="authenticationManager" ref="authenticationManager" /> <property name="filterProcessesUrl" value="/back/j_spring_security_check" /> <!-- 认证错误页面,已经被覆盖,由urlStrategy决定--> <property name="authenticationFailureUrl" value="/admin/login/login.html?error" /> <!-- 认证成功页面--> <property name="defaultTargetUrl" value="/admin/web/main.html" /> <property name="alwaysUseDefaultTargetUrl" value="true" /> </bean>
通过对于两个过滤器的相关属性的不同配置,可以分别响应不同的请求,并定向到相应的页面,如上例,前台页面的登陆请求发送到/j_spring_security_check,而后台发送到/back/j_spring_security_check,根据认证的结果分别转到到相应的
defaultTargetUrl或者authenticationFailureUrl。相应的logoutfilter也可以如此实现,通过这四个过滤器,我们可解决
以上问题中的2,3,4对于不同用户的登录和注销进行了相应处理。
<!-- 注销过滤器,完成前台用户注销时的定向功能 --> <bean id="preLogoutFilter" class="org.springframework.security.ui.logout.LogoutFilter"> <sec:custom-filter before="LOGOUT_FILTER" /> <constructor-arg value="/" /> <constructor-arg> <list> <bean class="org.springframework.security.ui.logout.SecurityContextLogoutHandler" /> </list> </constructor-arg> <property name="filterProcessesUrl" value="/j_spring_security_logout" /> </bean> <!-- 注销过滤器,完成后台管理员注销时的定向功能 --> <bean id="adminLogoutFilter" class="org.springframework.security.ui.logout.LogoutFilter"> <sec:custom-filter position="LOGOUT_FILTER" /> <constructor-arg value="/admin/login/login.html" /> <constructor-arg> <list> <bean class="org.springframework.security.ui.logout.SecurityContextLogoutHandler" /> </list> </constructor-arg> <property name="filterProcessesUrl" value="/back/j_spring_security_logout" /> </bean>
而对于问题1, 在downpour的文章中已经有解决,通过实现自己的AthenticationEntryPoint来控制没有登录的用户访问受限的页面。
至此,通过增加几个过滤器的方法,我们可以使用Spring Security2完成对多登录页面的情况的处理,相比以前的Acegi的繁琐配置,SS2的优势不言而喻