一、web.xml的配置(摘自:
http://blog.csdn.net/anyoneking/article/details/1748317)
(1) FilterToBeanProxy
Acegi通过实现了Filter接口的FilterToBeanProxy提供一种特殊的使用Servlet Filter的方式,它委托Spring 中的Bean -- FilterChainProxy来完成过滤功能,这好处是简化了web.xml的配置,并且充分利用了Spring IOC的优 势。FilterChainProxy包含了处理认证过程的filter列表,每个filter都有各自的功能。
<filter>
<filter-name>Spring Security Filter Chain Proxy</filter-name>
<filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
<init-param>
<param-name>targetClass</param-name>
<param-value>org.acegisecurity.util.FilterChainProxy</param-value>
</init-param>
</filter>
(2) filter-mapping
<filter-mapping>限定了FilterToBeanProxy的URL匹配模式,现在用/匹配所有URL。
<filter-mapping>
<filter-name>Spring Security Filter Chain Proxy</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
(3) HttpSessionEventPublisher
ContextLoaderListener的作用就是启动Web容器时,自动装配ApplicationContext的配置信息。
HttpSessionEventPublisher用于发布 HttpSessionApplicationEvents和HttpSessionDestroyedEvent事件给spring的 applicationcontext。
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.acegisecurity.ui.session.HttpSessionEventPublisher</listener-class>
</listener>
二、过滤器的配置(参考自 http://eryk.iteye.com/blog/626651 spring security 11种过滤器介绍 )
1、channelProcessingFilter
请求通过ChannelProcessingFilter(通道处理过滤器,可选)。该过滤器负责检查当前请求的Channel,并判断是否已满足安全需要。如果不满足,则由非安全的通道传输(Http)重定向于安全的通道传输(Https),以确保服务器与浏览器之间传输的数据加密。
(1)、在filterChainProxy里面加上channelProcessingFilter
<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT /**=channelProcessingFilter,concurrentSessionFilter,httpSessionIntegrationFilter,logoutFilter,authenticationProcessingFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor
</value>
</property>
</bean>
(2)、配置channelProcessingFilter
<!-- 通道安全过滤器 -->
<bean id="channelProcessingFilter" class="org.acegisecurity.securechannel.ChannelProcessingFilter">
<property name="filterInvocationDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/login.jsp=REQUIRES_INSECURE_CHANNEL
/j_acegi_security_check*=REQUIRES_INSECURE_CHANNEL
/**=REQUIRES_INSECURE_CHANNEL
</value>
</property>
<property name="channelDecisionManager" ref="channelDecisionManager"></property>
</bean>
<!-- 通道安全管理器 -->
<bean id="channelDecisionManager" class="org.acegisecurity.securechannel.ChannelDecisionManagerImpl">
<property name="channelProcessors">
<list>
<bean class="org.acegisecurity.securechannel.SecureChannelProcessor"></bean>
<bean class="org.acegisecurity.securechannel.InsecureChannelProcessor"></bean>
</list>
</property>
</bean>
2、concurrentSessionFilter
concurrentSessionFilter用于限制用户重复登录。
(1)、在filterChainProxy里面加上concurrentSessionFilter
(2)、配置concurrentSessionFilter
<bean id="concurrentSessionFilter" class="org.acegisecurity.concurrent.ConcurrentSessionFilter">
<property name="sessionRegistry" ref="sessionRegistry" />
<property name="expiredUrl" value="/login.jsp" />
</bean>
<bean id="sessionRegistry" class="org.acegisecurity.concurrent.SessionRegistryImpl" />
(3)、配置concurrentSessionController,阻止用户在进行了一次成功登录以后再进行一次成功的登录,maximumSessions属性配置了只允许同一个用户登录系统一次,exceptionIfMaximumExceeded属性配 置了在进行第二次登录时是否让第一次登录失效。设置为true不允许第二次登录,设置为false表示第二次登录成功的同时让第一次登录失效:
<bean id="concurrentSessionController" class="org.acegisecurity.concurrent.ConcurrentSessionControllerImpl">
<property name="maximumSessions" value="1"></property>
<property name="sessionRegistry" ref="sessionRegistry"></property>
<property name="exceptionIfMaximumExceeded" value="false"></property>
</bean>
(4)、配置concurrentSessionController,并在authenticationManager里面配置了一个名为sessionController的Bean,即对concurrentSessionController的引用:
<bean id="authenticationManager" class="org.springframework.security.providers.ProviderManager">
...
<property name="sessionController">
<ref bean="concurrentSessionController"/>
</property>
</bean>
3、HttpSessionContextIntegrationFilter
用途一,在执行其他过滤器之前,率先判断用户的session中是否已经存在一个SecurityContext了。如果存在,就把SecurityContext拿出来,放到SecurityContextHolder中,供Spring Security的其他部分使用。如果不存在,就创建一个SecurityContext出来,还是放到SecurityContextHolder中,供Spring Security的其他部分使用。
用途二,在所有过滤器执行完毕后,清空SecurityContextHolder,因为SecurityContextHolder是基于ThreadLocal的,如果在操作完成后清空ThreadLocal,会受到服务器的线程池机制的影响。
(1)、在filterChainProxy里面加上HttpSessionContextIntegrationFilter
(2)、配置HttpSessionContextIntegrationFilter
<!-- 安全上下文过滤器 -->
<bean id="httpSessionIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter"></bean>
4、logoutFilter
只处理注销请求,默认为/j_spring_security_logout。
用途是在用户发送注销请求时,销毁用户session,清空SecurityContextHolder,然后重定向到注销成功页面。可以与rememberMe之类的机制结合,在注销的同时清空用户cookie。
(1)、在filterChainProxy里面加上logoutFilter
(2)、配置logoutFilter
<!-- 退出过滤器 -->
<bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
<constructor-arg value="/login.jsp" />
<constructor-arg>
<list>
<bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
</list>
</constructor-arg>
</bean>
5、authenticationProcessingFilter
处理form登陆的过滤器,与form登陆有关的所有操作都是在此进行的。
默认情况下只处理/j_spring_security_check请求,这个请求应该是用户使用form登陆后的提交地址,form所需的其他参数可以参考:
此过滤器执行的基本操作时,通过用户名和密码判断用户是否有效,如果登录成功就跳转到成功页面(可能是登陆之前访问的受保护页面,也可能是默认的成功页面),如果登录失败,就跳转到失败页面。
(1)、配置前端页面
<form action="${pageContext.request.contextPath}/j_spring_security_check" style="width:260px;text-align:center;">
<fieldset>
<legend>登陆</legend>
用户: <input type="text" name="j_username" style="width:150px;" value="${sessionScope['SPRING_SECURITY_LAST_USERNAME']}"/><br />
密码: <input type="password" name="j_password" style="width:150px;" /><br />
<input type="checkbox" name="_spring_security_remember_me" />两周之内不必登陆<br />
<input type="submit" value="登陆"/>
<input type="reset" value="重置"/>
</fieldset>
</form>
/j_spring_security_check,提交登陆信息的URL地址。
自定义form时,要把form的action设置为/j_spring_security_check。注意这里要使用绝对路径,避免登陆页面存放的页面可能带来的问题。
j_username,输入登陆名的参数名称。
j_password,输入密码的参数名称
_spring_security_remember_me,选择是否允许自动登录的参数名称,可以直接把这个参数设置为一个checkbox,无需设置value,Spring Security会自行判断它是否被选中,与rememberMe机制结合使用。
(2)、在filterChainProxy里面加上authenticationProcessingFilter
(3)、配置authenticationProcessingFilter
<!-- 表单认证过滤器 -->
<bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
<property name="filterProcessesUrl" value="/j_acegi_security_check"></property><!--需要认证的URL-->
<property name="authenticationFailureUrl" value="/login.jsp?login_err=1"></property><!--登录失败转向页面-->
<property name="defaultTargetUrl" value="/admin.jsp"></property><!--登录成功转向页面-->
<property name="authenticationManager" ref="authenticationManager"></property>
</bean>
(4)、配置认证管理器authenticationManager
<!-- 认证管理器 -->
<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
<property name="providers">
<list>
<ref bean="authenticationProvider"/>
</list>
</property>
</bean>
(5)、配置认证提供者authenticationProvider
<bean id="authenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
<property name="userDetailsService" ref="userDetailsService"></property>
<property name="passwordEncoder">
<bean class="org.acegisecurity.providers.encoding.Md5PasswordEncoder"></bean>
</property>
<!--种子源是和密码结合进行md5加密的,默认为"密码{ABC123XYZ789}"-->
<property name="saltSource">
<bean class="org.acegisecurity.providers.dao.salt.SystemWideSaltSource">
<property name="systemWideSalt" value="ABC123XYZ789"></property>
</bean>
</property>
<property name="userCache">
<bean class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache">
<property name="cache" ref="ehcache"></property>
</bean>
</property>
</bean>
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager" ref="cacheManager"></property>
<property name="cacheName" value="rantzCache"></property>
</bean>
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml"></property>
</bean>
<!-- 用户信息源(数据库) -->
<bean id="userDetailsService" class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl">
<property name="dataSource" ref="dataSource"></property>
<property name="usersByUsernameQuery">
<value>
SELECT email as username,password,'1' as enabled <!-- enabled必须为数字,0表示false,1表示true -->
FROM Motorist
WHERE email = ?
</value>
</property>
<property name="authoritiesByUsernameQuery">
<value>
SELECT email as username,privilege as authority
FROM Motorist_privileges mp,Motorist m
WHERE mp.motorist_id=m.id AND m.email=?
</value>
</property>
</bean>
6、rememberMeProcessingFilter
此过滤器实现RememberMe功能,当用户cookie中存在rememberMe的标记,此过滤器会根据标记自动实现用户登陆,并创建SecurityContext,授予对应的权限。
实际上,Spring Security中的rememberMe是依赖cookie实现的,当用户在登录时选择使用rememberMe,系统就会在登录成功后将为用户生成一个唯一标识,并将这个标识保存进cookie中,我们可以通过浏览器查看用户电脑中的cookie。
(1)、配置rememberMeProcessingFilter
<!-- 免登录认证过滤器 -->
<bean id="rememberMeProcessingFilter"
class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
<property name="rememberMeServices" ref="rememberMeServices" />
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<!-- 免登录服务 -->
<bean id="rememberMeServices"
class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">
<property name="userDetailsService" ref="userDetailsService" />
<property name="key" value="springRocks" /><!--与rememberMeAuthenticationProvider中的key要相同-->
<property name="tokenValiditySeconds" value="1209600L"></property><!--免登陆时长,默认为1209600秒,即两周-->
</bean>
<!-- 免登录认证源提供者 -->
<bean id="rememberMeAuthenticationProvider" class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
<property name="key" value="springRocks"></property>
</bean>
(2)、不要忘记把你的RememberMeServices实现添加到AuthenticationProcessingFilter.setRememberMeServices()属性中,包括把RememberMeAuthenticationProvider添加到你的AuthenticationManager.setProviders()队列中,把RememberMeProcessingFilter添加到你的FilterChainProxy中(要放到AuthenticationProcessingFilter后面),并且在httpSessionIntegrationFilter中配置forceEagerSessionCreation=true,如果退出时想取消自动登录功能,需要在退出过滤器logoutFilter中配置rememberMeServices。
<!-- 表单认证过滤器 -->
<bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
<property name="filterProcessesUrl" value="/j_acegi_security_check"></property>
<property name="authenticationFailureUrl" value="/login.jsp?login_err=1"></property>
<property name="defaultTargetUrl" value="/admin.jsp"></property>
<property name="authenticationManager" ref="authenticationManager"></property>
<property name="rememberMeServices" ref="rememberMeServices"></property>
</bean>
<!-- 认证管理器 -->
<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
<property name="providers">
<list>
<ref bean="authenticationProvider"/>
<ref bean="rememberMeAuthenticationProvider"/>
</list>
</property>
<property name="sessionController" ref="concurrentSessionController"></property>
</bean>
<!-- 安全上下文过滤器 -->
<bean id="httpSessionIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter">
<!-- 为了能够提前获得用户session的值,在rememberMeProcessingFilter应用的时候必须设置 -->
<property name="forceEagerSessionCreation">
<value>true</value>
</property>
</bean>
<!-- 退出过滤器 -->
<bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
<constructor-arg value="/login.jsp" />
<constructor-arg>
<list>
<!-- 用于退出rememberMeServices所存储在session中的用户 -->
<ref bean="rememberMeServices"/>
<bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
</list>
</constructor-arg>
</bean>
7、anonymousProcessingFilter
为了保证操作统一性,当用户没有登陆时,默认为用户分配匿名用户的权限。
(1)、配置anonymousProcessingFilter
<!-- 匿名过滤器 -->
<bean id="anonymousProcessingFilter" class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter">
<property name="key" value="foobar"></property>
<property name="userAttribute" value="anonymousUser,GROUP_ANONYMOUS"></property><!--此为匿名用户名和权限-->
</bean>
<bean id="anonymousAuthenticationProvider" class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
<property name="key" value="foobar"></property>
</bean>
(2)把anonymousAuthenticationProvider添加到你的AuthenticationManager.setProviders()队列中
<!-- 认证管理器 -->
<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
<property name="providers">
<list>
<ref bean="authenticationProvider"/>
<ref bean="anonymousAuthenticationProvider"/>
<ref bean="rememberMeAuthenticationProvider"/>
</list>
</property>
<property name="sessionController" ref="concurrentSessionController"></property>
</bean>
8、exceptionTranslationFilter
此过滤器的作用是处理中FilterSecurityInterceptor抛出的异常,然后将请求重定向到对应页面,或返回对应的响应错误代码。
(1)、配置exceptionTranslationFilter
<!-- 异常处理过滤器 -->
<bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
<property name="authenticationEntryPoint" ref="authenticationEntryPoint"></property>
<property name="accessDeniedHandler" ref="accessDeniedHandler"></property>
</bean>
<!-- 授权拒绝句柄 -->
<bean id="accessDeniedHandler" class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
<property name="errorPage" value="/error.jsp"></property><!--权限错误时跳转的页面-->
</bean>
<!-- 表单认证入口点 -->
<bean id="authenticationEntryPoint" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl" value="/login.jsp"></property> <!--还没有登录时,无权限跳转的页面-->
<property name="serverSideRedirect" value="false"></property> <!--是否重定向页面-->
</bean>
9、FilterSecurityInterceptor
用户的权限控制都包含在这个过滤器中。
功能一:如果用户尚未登陆,则抛出AuthenticationCredentialsNotFoundException“尚未认证异常”。
功能二:如果用户已登录,但是没有访问当前资源的权限,则抛出AccessDeniedException“拒绝访问异常”。
功能三:如果用户已登录,也具有访问当前资源的权限,则放行。
(1)、配置exceptionTranslationFilter
<bean id="filterSecurityInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
<property name="accessDecisionManager" ref="accessDecisionManager"></property>
<property name="authenticationManager" ref="authenticationManager"></property>
<property name="objectDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/admin.jsp=GROUP_MOTORIST
/user.jsp=GROUP_ANONYMOUS
</value>
</property>
</bean>
<!-- 访问决策管理器 -->
<bean id="accessDecisionManager" class="org.acegisecurity.vote.UnanimousBased">
<property name="decisionVoters">
<list>
<ref bean="roleVoter"/>
</list>
</property>
<property name="allowIfAllAbstainDecisions" value="true"></property>
</bean>
<bean id="roleVoter" class="org.acegisecurity.vote.RoleVoter">
<property name="rolePrefix" value="GROUP_">
</property>
</bean>
(1) FilterToBeanProxy
Acegi通过实现了Filter接口的FilterToBeanProxy提供一种特殊的使用Servlet Filter的方式,它委托Spring 中的Bean -- FilterChainProxy来完成过滤功能,这好处是简化了web.xml的配置,并且充分利用了Spring IOC的优 势。FilterChainProxy包含了处理认证过程的filter列表,每个filter都有各自的功能。
<filter>
<filter-name>Spring Security Filter Chain Proxy</filter-name>
<filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
<init-param>
<param-name>targetClass</param-name>
<param-value>org.acegisecurity.util.FilterChainProxy</param-value>
</init-param>
</filter>
(2) filter-mapping
<filter-mapping>限定了FilterToBeanProxy的URL匹配模式,现在用/匹配所有URL。
<filter-mapping>
<filter-name>Spring Security Filter Chain Proxy</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
(3) HttpSessionEventPublisher
ContextLoaderListener的作用就是启动Web容器时,自动装配ApplicationContext的配置信息。
HttpSessionEventPublisher用于发布 HttpSessionApplicationEvents和HttpSessionDestroyedEvent事件给spring的 applicationcontext。
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.acegisecurity.ui.session.HttpSessionEventPublisher</listener-class>
</listener>
二、过滤器的配置(参考自 http://eryk.iteye.com/blog/626651 spring security 11种过滤器介绍 )
1、channelProcessingFilter
请求通过ChannelProcessingFilter(通道处理过滤器,可选)。该过滤器负责检查当前请求的Channel,并判断是否已满足安全需要。如果不满足,则由非安全的通道传输(Http)重定向于安全的通道传输(Https),以确保服务器与浏览器之间传输的数据加密。
(1)、在filterChainProxy里面加上channelProcessingFilter
<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT /**=channelProcessingFilter,concurrentSessionFilter,httpSessionIntegrationFilter,logoutFilter,authenticationProcessingFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor
</value>
</property>
</bean>
(2)、配置channelProcessingFilter
<!-- 通道安全过滤器 -->
<bean id="channelProcessingFilter" class="org.acegisecurity.securechannel.ChannelProcessingFilter">
<property name="filterInvocationDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/login.jsp=REQUIRES_INSECURE_CHANNEL
/j_acegi_security_check*=REQUIRES_INSECURE_CHANNEL
/**=REQUIRES_INSECURE_CHANNEL
</value>
</property>
<property name="channelDecisionManager" ref="channelDecisionManager"></property>
</bean>
<!-- 通道安全管理器 -->
<bean id="channelDecisionManager" class="org.acegisecurity.securechannel.ChannelDecisionManagerImpl">
<property name="channelProcessors">
<list>
<bean class="org.acegisecurity.securechannel.SecureChannelProcessor"></bean>
<bean class="org.acegisecurity.securechannel.InsecureChannelProcessor"></bean>
</list>
</property>
</bean>
2、concurrentSessionFilter
concurrentSessionFilter用于限制用户重复登录。
(1)、在filterChainProxy里面加上concurrentSessionFilter
(2)、配置concurrentSessionFilter
<bean id="concurrentSessionFilter" class="org.acegisecurity.concurrent.ConcurrentSessionFilter">
<property name="sessionRegistry" ref="sessionRegistry" />
<property name="expiredUrl" value="/login.jsp" />
</bean>
<bean id="sessionRegistry" class="org.acegisecurity.concurrent.SessionRegistryImpl" />
(3)、配置concurrentSessionController,阻止用户在进行了一次成功登录以后再进行一次成功的登录,maximumSessions属性配置了只允许同一个用户登录系统一次,exceptionIfMaximumExceeded属性配 置了在进行第二次登录时是否让第一次登录失效。设置为true不允许第二次登录,设置为false表示第二次登录成功的同时让第一次登录失效:
<bean id="concurrentSessionController" class="org.acegisecurity.concurrent.ConcurrentSessionControllerImpl">
<property name="maximumSessions" value="1"></property>
<property name="sessionRegistry" ref="sessionRegistry"></property>
<property name="exceptionIfMaximumExceeded" value="false"></property>
</bean>
(4)、配置concurrentSessionController,并在authenticationManager里面配置了一个名为sessionController的Bean,即对concurrentSessionController的引用:
<bean id="authenticationManager" class="org.springframework.security.providers.ProviderManager">
...
<property name="sessionController">
<ref bean="concurrentSessionController"/>
</property>
</bean>
3、HttpSessionContextIntegrationFilter
用途一,在执行其他过滤器之前,率先判断用户的session中是否已经存在一个SecurityContext了。如果存在,就把SecurityContext拿出来,放到SecurityContextHolder中,供Spring Security的其他部分使用。如果不存在,就创建一个SecurityContext出来,还是放到SecurityContextHolder中,供Spring Security的其他部分使用。
用途二,在所有过滤器执行完毕后,清空SecurityContextHolder,因为SecurityContextHolder是基于ThreadLocal的,如果在操作完成后清空ThreadLocal,会受到服务器的线程池机制的影响。
(1)、在filterChainProxy里面加上HttpSessionContextIntegrationFilter
(2)、配置HttpSessionContextIntegrationFilter
<!-- 安全上下文过滤器 -->
<bean id="httpSessionIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter"></bean>
4、logoutFilter
只处理注销请求,默认为/j_spring_security_logout。
用途是在用户发送注销请求时,销毁用户session,清空SecurityContextHolder,然后重定向到注销成功页面。可以与rememberMe之类的机制结合,在注销的同时清空用户cookie。
(1)、在filterChainProxy里面加上logoutFilter
(2)、配置logoutFilter
<!-- 退出过滤器 -->
<bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
<constructor-arg value="/login.jsp" />
<constructor-arg>
<list>
<bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
</list>
</constructor-arg>
</bean>
5、authenticationProcessingFilter
处理form登陆的过滤器,与form登陆有关的所有操作都是在此进行的。
默认情况下只处理/j_spring_security_check请求,这个请求应该是用户使用form登陆后的提交地址,form所需的其他参数可以参考:
此过滤器执行的基本操作时,通过用户名和密码判断用户是否有效,如果登录成功就跳转到成功页面(可能是登陆之前访问的受保护页面,也可能是默认的成功页面),如果登录失败,就跳转到失败页面。
(1)、配置前端页面
<form action="${pageContext.request.contextPath}/j_spring_security_check" style="width:260px;text-align:center;">
<fieldset>
<legend>登陆</legend>
用户: <input type="text" name="j_username" style="width:150px;" value="${sessionScope['SPRING_SECURITY_LAST_USERNAME']}"/><br />
密码: <input type="password" name="j_password" style="width:150px;" /><br />
<input type="checkbox" name="_spring_security_remember_me" />两周之内不必登陆<br />
<input type="submit" value="登陆"/>
<input type="reset" value="重置"/>
</fieldset>
</form>
/j_spring_security_check,提交登陆信息的URL地址。
自定义form时,要把form的action设置为/j_spring_security_check。注意这里要使用绝对路径,避免登陆页面存放的页面可能带来的问题。
j_username,输入登陆名的参数名称。
j_password,输入密码的参数名称
_spring_security_remember_me,选择是否允许自动登录的参数名称,可以直接把这个参数设置为一个checkbox,无需设置value,Spring Security会自行判断它是否被选中,与rememberMe机制结合使用。
(2)、在filterChainProxy里面加上authenticationProcessingFilter
(3)、配置authenticationProcessingFilter
<!-- 表单认证过滤器 -->
<bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
<property name="filterProcessesUrl" value="/j_acegi_security_check"></property><!--需要认证的URL-->
<property name="authenticationFailureUrl" value="/login.jsp?login_err=1"></property><!--登录失败转向页面-->
<property name="defaultTargetUrl" value="/admin.jsp"></property><!--登录成功转向页面-->
<property name="authenticationManager" ref="authenticationManager"></property>
</bean>
(4)、配置认证管理器authenticationManager
<!-- 认证管理器 -->
<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
<property name="providers">
<list>
<ref bean="authenticationProvider"/>
</list>
</property>
</bean>
(5)、配置认证提供者authenticationProvider
<bean id="authenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
<property name="userDetailsService" ref="userDetailsService"></property>
<property name="passwordEncoder">
<bean class="org.acegisecurity.providers.encoding.Md5PasswordEncoder"></bean>
</property>
<!--种子源是和密码结合进行md5加密的,默认为"密码{ABC123XYZ789}"-->
<property name="saltSource">
<bean class="org.acegisecurity.providers.dao.salt.SystemWideSaltSource">
<property name="systemWideSalt" value="ABC123XYZ789"></property>
</bean>
</property>
<property name="userCache">
<bean class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache">
<property name="cache" ref="ehcache"></property>
</bean>
</property>
</bean>
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager" ref="cacheManager"></property>
<property name="cacheName" value="rantzCache"></property>
</bean>
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml"></property>
</bean>
<!-- 用户信息源(数据库) -->
<bean id="userDetailsService" class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl">
<property name="dataSource" ref="dataSource"></property>
<property name="usersByUsernameQuery">
<value>
SELECT email as username,password,'1' as enabled <!-- enabled必须为数字,0表示false,1表示true -->
FROM Motorist
WHERE email = ?
</value>
</property>
<property name="authoritiesByUsernameQuery">
<value>
SELECT email as username,privilege as authority
FROM Motorist_privileges mp,Motorist m
WHERE mp.motorist_id=m.id AND m.email=?
</value>
</property>
</bean>
6、rememberMeProcessingFilter
此过滤器实现RememberMe功能,当用户cookie中存在rememberMe的标记,此过滤器会根据标记自动实现用户登陆,并创建SecurityContext,授予对应的权限。
实际上,Spring Security中的rememberMe是依赖cookie实现的,当用户在登录时选择使用rememberMe,系统就会在登录成功后将为用户生成一个唯一标识,并将这个标识保存进cookie中,我们可以通过浏览器查看用户电脑中的cookie。
(1)、配置rememberMeProcessingFilter
<!-- 免登录认证过滤器 -->
<bean id="rememberMeProcessingFilter"
class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
<property name="rememberMeServices" ref="rememberMeServices" />
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<!-- 免登录服务 -->
<bean id="rememberMeServices"
class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">
<property name="userDetailsService" ref="userDetailsService" />
<property name="key" value="springRocks" /><!--与rememberMeAuthenticationProvider中的key要相同-->
<property name="tokenValiditySeconds" value="1209600L"></property><!--免登陆时长,默认为1209600秒,即两周-->
</bean>
<!-- 免登录认证源提供者 -->
<bean id="rememberMeAuthenticationProvider" class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
<property name="key" value="springRocks"></property>
</bean>
(2)、不要忘记把你的RememberMeServices实现添加到AuthenticationProcessingFilter.setRememberMeServices()属性中,包括把RememberMeAuthenticationProvider添加到你的AuthenticationManager.setProviders()队列中,把RememberMeProcessingFilter添加到你的FilterChainProxy中(要放到AuthenticationProcessingFilter后面),并且在httpSessionIntegrationFilter中配置forceEagerSessionCreation=true,如果退出时想取消自动登录功能,需要在退出过滤器logoutFilter中配置rememberMeServices。
<!-- 表单认证过滤器 -->
<bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
<property name="filterProcessesUrl" value="/j_acegi_security_check"></property>
<property name="authenticationFailureUrl" value="/login.jsp?login_err=1"></property>
<property name="defaultTargetUrl" value="/admin.jsp"></property>
<property name="authenticationManager" ref="authenticationManager"></property>
<property name="rememberMeServices" ref="rememberMeServices"></property>
</bean>
<!-- 认证管理器 -->
<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
<property name="providers">
<list>
<ref bean="authenticationProvider"/>
<ref bean="rememberMeAuthenticationProvider"/>
</list>
</property>
<property name="sessionController" ref="concurrentSessionController"></property>
</bean>
<!-- 安全上下文过滤器 -->
<bean id="httpSessionIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter">
<!-- 为了能够提前获得用户session的值,在rememberMeProcessingFilter应用的时候必须设置 -->
<property name="forceEagerSessionCreation">
<value>true</value>
</property>
</bean>
<!-- 退出过滤器 -->
<bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
<constructor-arg value="/login.jsp" />
<constructor-arg>
<list>
<!-- 用于退出rememberMeServices所存储在session中的用户 -->
<ref bean="rememberMeServices"/>
<bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
</list>
</constructor-arg>
</bean>
7、anonymousProcessingFilter
为了保证操作统一性,当用户没有登陆时,默认为用户分配匿名用户的权限。
(1)、配置anonymousProcessingFilter
<!-- 匿名过滤器 -->
<bean id="anonymousProcessingFilter" class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter">
<property name="key" value="foobar"></property>
<property name="userAttribute" value="anonymousUser,GROUP_ANONYMOUS"></property><!--此为匿名用户名和权限-->
</bean>
<bean id="anonymousAuthenticationProvider" class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
<property name="key" value="foobar"></property>
</bean>
(2)把anonymousAuthenticationProvider添加到你的AuthenticationManager.setProviders()队列中
<!-- 认证管理器 -->
<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
<property name="providers">
<list>
<ref bean="authenticationProvider"/>
<ref bean="anonymousAuthenticationProvider"/>
<ref bean="rememberMeAuthenticationProvider"/>
</list>
</property>
<property name="sessionController" ref="concurrentSessionController"></property>
</bean>
8、exceptionTranslationFilter
此过滤器的作用是处理中FilterSecurityInterceptor抛出的异常,然后将请求重定向到对应页面,或返回对应的响应错误代码。
(1)、配置exceptionTranslationFilter
<!-- 异常处理过滤器 -->
<bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
<property name="authenticationEntryPoint" ref="authenticationEntryPoint"></property>
<property name="accessDeniedHandler" ref="accessDeniedHandler"></property>
</bean>
<!-- 授权拒绝句柄 -->
<bean id="accessDeniedHandler" class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
<property name="errorPage" value="/error.jsp"></property><!--权限错误时跳转的页面-->
</bean>
<!-- 表单认证入口点 -->
<bean id="authenticationEntryPoint" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl" value="/login.jsp"></property> <!--还没有登录时,无权限跳转的页面-->
<property name="serverSideRedirect" value="false"></property> <!--是否重定向页面-->
</bean>
9、FilterSecurityInterceptor
用户的权限控制都包含在这个过滤器中。
功能一:如果用户尚未登陆,则抛出AuthenticationCredentialsNotFoundException“尚未认证异常”。
功能二:如果用户已登录,但是没有访问当前资源的权限,则抛出AccessDeniedException“拒绝访问异常”。
功能三:如果用户已登录,也具有访问当前资源的权限,则放行。
(1)、配置exceptionTranslationFilter
<bean id="filterSecurityInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
<property name="accessDecisionManager" ref="accessDecisionManager"></property>
<property name="authenticationManager" ref="authenticationManager"></property>
<property name="objectDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/admin.jsp=GROUP_MOTORIST
/user.jsp=GROUP_ANONYMOUS
</value>
</property>
</bean>
<!-- 访问决策管理器 -->
<bean id="accessDecisionManager" class="org.acegisecurity.vote.UnanimousBased">
<property name="decisionVoters">
<list>
<ref bean="roleVoter"/>
</list>
</property>
<property name="allowIfAllAbstainDecisions" value="true"></property>
</bean>
<bean id="roleVoter" class="org.acegisecurity.vote.RoleVoter">
<property name="rolePrefix" value="GROUP_">
</property>
</bean>