使用Spring Security 3 来实现多种用户类型的登录方式,在我看来,大致分为两大步,第一步是控制多种用户登录类型的登录界面的展示,第二步是控制多种用户登录的验证方式,而第二大步又可分为三个小步来展开,第一小步是验证过滤器,第二小步是验证凭证的制作,第三小步是验证用户凭证,在这里我将就这几步的分析与实现一步一步展开来进行描述。
这里我假定有这样一个系统,分为前台用户和后台用户两种用户类型,针对这两种不同的用户,相应的验证是不一样的,前台用户登录需要提供邮箱地址和电话号码,而后台用户需要提供我们在登录方式中最为常见的用户名,密码和验证码,两种登录类型的登录界面和登录的验证处理流程都不相同,拥有自己的验证处理,验证成功的处理,验证失败的处理等。这里我会用四篇文章来详细阐述整个验证的流程实现,每一篇文章后都会附有我的项目压缩文件,有兴趣的朋友可以下载来进行尝试,我使用的是Maven来管理项目,项目的框架是Spring+Hibernate,使用到的开发工具是IntelliJ,这里我要给IntelliJ打个广告,当然是无偿的,呵呵,在这之前我曾使用过NetBeans,Eclipse等开发工具,IntelliJ是我使用过的最为优秀的开发工具,有兴趣的同学可以尝试下。
Spring Security 3多用户登录实现之二 多登录界面展示
接前讲,首先针对一个多种用户类型的登录需求,需要先实现多种用户类型的登录界面的展示,Spring Security提供了这样一个接口来帮助我们实现多种用户类型的登录界面的展示,这个接口就是AuthenticationEntryPoint, 实现这样一个接口,我们就可以随心所欲的控制登录界面的展示了,当我们访问一个受权限的资源,而当前又没有权限访问时,Spring Security就会将处理导向这个接口的实现。针对前讲我所提到的需求,在这里我将实现前台用户和后台用户登录界面的展示,先来看看我的源码实现吧,在这里为了实现多用户类型的登录,很多场景我都需要根据相应的请求参数或地址来判断我需要导向哪个URL地址,我在这里特实现了一个共用的接口和类,接口名为DirectUrlResolver。
- package com.template.security.shared;
- import javax.servlet.http.HttpServletRequest;
- /**
- * Created by IntelliJ IDEA.
- * User: Zhong Gang
- * Date: 12-11-9
- * Time: 下午7:11
- */
- public interface DirectUrlResolver {
- boolean support(HttpServletRequest request);
- String directUrl();
- }
- package com.template.security.shared;
- import javax.servlet.http.HttpServletRequest;
- /**
- * Created by IntelliJ IDEA.
- * User: Zhong Gang
- * Date: 12-11-9
- * Time: 下午7:12
- */
- public abstract class AbstractDirectUrlResolver implements DirectUrlResolver {
- protected String pattern;
- protected String directUrl;
- @Override
- public abstract boolean support(HttpServletRequest request);
- @Override
- public String directUrl() {
- return this.directUrl;
- }
- public void setPattern(String pattern) {
- this.pattern = pattern;
- }
- public void setDirectUrl(String directUrl) {
- this.directUrl = directUrl;
- }
- }
- package com.template.security.shared;
- import com.template.utils.StringUtils;
- import javax.servlet.http.HttpServletRequest;
- /**
- * Created by IntelliJ IDEA.
- * User: Zhong Gang
- * Date: 12-11-9
- * Time: 下午7:13
- */
- public class RequestParameterDirectUrlResolver extends AbstractDirectUrlResolver {
- private String parameterName;
- @Override
- public boolean support(HttpServletRequest request) {
- String parameterValue = request.getParameter(parameterName);
- if (StringUtils.isEmpty(parameterValue)) {
- return false;
- }
- return parameterValue.equals(this.pattern);
- }
- public void setParameterName(String parameterName) {
- this.parameterName = parameterName;
- }
- }
- package com.template.security.shared;
- import javax.servlet.http.HttpServletRequest;
- /**
- * Created by IntelliJ IDEA.
- * User: Zhong Gang
- * Date: 12-11-9
- * Time: 下午7:13
- */
- public class RequestUriDirectUrlResolver extends AbstractDirectUrlResolver {
- @Override
- public boolean support(HttpServletRequest request) {
- String requestURI = request.getRequestURI();
- return requestURI.contains(this.pattern);
- }
- }
RequestParameterDirectUrlResolver和RequestUriDirectUrlResolver都实现了DirectUrlResolver这样一个接口,前者的实现是根据相应请求中的参数来判断, 而后者的实现是根据相应的请求地址来判断。
现在让我们来看看如何通过实现AuthenticationEntryPoint接口来控制什么时候展示前台登录界面,什么时候展示后台登录界面的吧。
- package com.template.security.login;
- import com.template.security.shared.DirectUrlResolver;
- import org.springframework.security.core.AuthenticationException;
- import org.springframework.security.web.AuthenticationEntryPoint;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
- import java.util.ArrayList;
- import java.util.List;
- /**
- * Created by IntelliJ IDEA.
- * User: Zhong Gang
- * Date: 12-11-9
- * Time: 下午7:40
- */
- public class MultipleAuthenticationLoginEntry implements AuthenticationEntryPoint {
- private String defaultLoginUrl;
- private List<DirectUrlResolver> directUrlResolvers = new ArrayList<DirectUrlResolver>();
- @Override
- public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
- for (DirectUrlResolver directUrlResolver : directUrlResolvers) {
- if (directUrlResolver.support(request)) {
- String loginUrl = directUrlResolver.directUrl();
- response.sendRedirect(loginUrl);
- return;
- }
- }
- response.sendRedirect(defaultLoginUrl);
- }
- public void setDefaultLoginUrl(String defaultLoginUrl) {
- this.defaultLoginUrl = defaultLoginUrl;
- }
- public void setDirectUrlResolvers(List<DirectUrlResolver> directUrlResolvers) {
- this.directUrlResolvers = directUrlResolvers;
- }
- }
再来看看在Spring配置文件中是如何对相应的登录入口进行配置的吧
- <beans:bean id="multipleAuthenticationLoginEntry"
- class="com.template.security.login.MultipleAuthenticationLoginEntry">
- <beans:property name="defaultLoginUrl" value="/backend/login"/>
- <beans:property name="directUrlResolvers">
- <beans:list>
- <beans:ref bean="backendLoginEntry"/>
- <beans:ref bean="forendLoginEntry"/>
- </beans:list>
- </beans:property>
- </beans:bean>
- <beans:bean id="backendLoginEntry" class="com.template.security.shared.RequestUriDirectUrlResolver">
- <beans:property name="pattern" value="/backend"/>
- <beans:property name="directUrl" value="/backend/login"/>
- </beans:bean>
- <beans:bean id="forendLoginEntry" class="com.template.security.shared.RequestUriDirectUrlResolver">
- <beans:property name="pattern" value="/forend"/>
- <beans:property name="directUrl" value="/forend/login"/>
- </beans:bean>
这里我是根据请求的地址中是否包括backend或forend来判断用户是进行前台登录或后台登录的, 这可以从配置文件中的backendLoginEntry和forendLoginEntry中的pattern属性看出,这个pattern的作用就是判断用户是进行前台登录或后台登录的依据,而directUrl则是我们想要导向的登录界面地址。
Spring Security 3多用户登录实现之三 验证过滤器
当填写完成登录表单提交后,首先会被对应的提交表单提起的过滤器进行拦截,这里过滤器的作用就是拦截登录表单提交验证请求,并根据相应的表单信息构造对应的登录凭证,这里来看看过滤器是如何构造相应的用户凭证。
- package com.template.security.filter;
- import org.springframework.security.core.Authentication;
- import org.springframework.security.core.AuthenticationException;
- import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
- import java.util.ArrayList;
- import java.util.List;
- /**
- * Created by IntelliJ IDEA.
- * User: Zhong Gang
- * Date: 12-11-9
- * Time: 下午10:00
- */
- public class MultipleAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter {
- private List<AuthenticationTokenResolver> tokenResolvers = new ArrayList<AuthenticationTokenResolver>();
- /**
- * @param defaultFilterProcessesUrl the default value for <tt>filterProcessesUrl</tt>.
- */
- protected MultipleAuthenticationProcessingFilter(String defaultFilterProcessesUrl) {
- super(defaultFilterProcessesUrl);
- }
- @Override
- public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
- for (AuthenticationTokenResolver tokenResolver : tokenResolvers) {
- if (tokenResolver.support(request)) {
- Authentication authentication = tokenResolver.resolve(request);
- return this.getAuthenticationManager().authenticate(authentication);
- }
- }
- throw new UnsupportedOperationException("No authentication token resolver found!");
- }
- public void setTokenResolvers(List<AuthenticationTokenResolver> tokenResolvers) {
- this.tokenResolvers = tokenResolvers;
- }
- }
- package com.template.security.filter;
- import org.springframework.security.core.Authentication;
- import javax.servlet.http.HttpServletRequest;
- /**
- * Created by IntelliJ IDEA.
- * User: Zhong Gang
- * Date: 12-11-9
- * Time: 下午10:08
- */
- public interface AuthenticationTokenResolver {
- boolean support(HttpServletRequest request);
- Authentication resolve(HttpServletRequest request);
- }
- package com.template.security.filter;
- import com.template.utils.StringUtils;
- import org.springframework.security.core.Authentication;
- import javax.servlet.http.HttpServletRequest;
- /**
- * Created by IntelliJ IDEA.
- * User: Zhong Gang
- * Date: 12-11-9
- * Time: 下午10:27
- */
- public abstract class AbstractAuthenticationTokenResolver implements AuthenticationTokenResolver {
- protected String parameterName;
- protected String parameterValue;
- protected AbstractAuthenticationTokenResolver() {
- }
- protected AbstractAuthenticationTokenResolver(String parameterName) {
- this.parameterName = parameterName;
- }
- @Override
- public boolean support(HttpServletRequest request) {
- String parameterValue = request.getParameter(parameterName);
- if (StringUtils.isEmpty(parameterValue)) {
- return false;
- }
- return parameterValue.equals(this.parameterValue);
- }
- @Override
- public abstract Authentication resolve(HttpServletRequest request);
- public void setParameterName(String parameterName) {
- this.parameterName = parameterName;
- }
- public void setParameterValue(String parameterValue) {
- this.parameterValue = parameterValue;
- }
- }
- package com.template.security.filter;
- import com.template.security.authentication.token.BackendAuthenticationToken;
- import org.springframework.security.core.Authentication;
- import org.springframework.security.core.GrantedAuthority;
- import org.springframework.security.core.authority.SimpleGrantedAuthority;
- import javax.servlet.http.HttpServletRequest;
- import java.util.ArrayList;
- import java.util.List;
- /**
- * Created by IntelliJ IDEA.
- * User: Zhong Gang
- * Date: 12-11-9
- * Time: 下午10:29
- */
- public class BackendAuthenticationTokenResolver extends AbstractAuthenticationTokenResolver {
- protected BackendAuthenticationTokenResolver() {
- super();
- }
- @Override
- public Authentication resolve(HttpServletRequest request) {
- String username = request.getParameter("username");
- String password = request.getParameter("password");
- String captcha = request.getParameter("captcha");
- List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
- authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
- return new BackendAuthenticationToken(username, password, authorities, captcha);
- }
- }
- package com.template.security.filter;
- import com.template.security.authentication.token.ForendAuthenticationToken;
- import org.springframework.security.core.Authentication;
- import org.springframework.security.core.GrantedAuthority;
- import org.springframework.security.core.authority.SimpleGrantedAuthority;
- import javax.servlet.http.HttpServletRequest;
- import java.util.ArrayList;
- import java.util.List;
- /**
- * Created by IntelliJ IDEA.
- * User: Zhong Gang
- * Date: 12-11-9
- * Time: 下午10:29
- */
- public class ForendAuthenticationTokenResolver extends AbstractAuthenticationTokenResolver {
- protected ForendAuthenticationTokenResolver() {
- super();
- }
- @Override
- public Authentication resolve(HttpServletRequest request) {
- String email = request.getParameter("email");
- String phone = request.getParameter("phone");
- List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
- authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
- return new ForendAuthenticationToken(email, phone, authorities);
- }
- }
这里实现AbstractAuthenticationProcessingFilter接口的类MultipleAuthenticationProcessingFilter,用来根据相应的登录表单提交信息构造相应的登录用户凭证。为了实现根据前台登录表单信息构造前台用户凭证,根据后台登录表单信息构造后台用户凭证,使用了策略模式来实现,实现AbstractAuthenticationTokenResolver接口的BackendAuthenticationTokenResolver和ForendAuthenticationTokenResolver分别用来构造后台用户凭证和前台用户凭证,再来看看配置文件是如何进行配置的吧。
- <beans:bean id="multipleAuthenticationProcessingFilter"
- class="com.template.security.filter.MultipleAuthenticationProcessingFilter">
- <beans:constructor-arg value="/login/check"/>
- <beans:property name="tokenResolvers">
- <beans:list>
- <beans:ref bean="backendAuthenticationTokenResolver"/>
- <beans:ref bean="forendAuthenticationTokenResolver"/>
- </beans:list>
- </beans:property>
- <beans:property name="authenticationManager" ref="authenticationManager"/>
- <beans:property name="authenticationSuccessHandler" ref="multipleAuthenticationSuccessHandler"/>
- <beans:property name="authenticationFailureHandler" ref="multipleAuthenticationFailureHandler"/>
- </beans:bean>
- <beans:bean id="backendAuthenticationTokenResolver"
- class="com.template.security.filter.BackendAuthenticationTokenResolver">
- <beans:property name="parameterName" value="token"/>
- <beans:property name="parameterValue" value="backend"/>
- </beans:bean>
- <beans:bean id="forendAuthenticationTokenResolver"
- class="com.template.security.filter.ForendAuthenticationTokenResolver">
- <beans:property name="parameterName" value="token"/>
- <beans:property name="parameterValue" value="forend"/>
- </beans:bean>
这里不论是前台登录还是后台登录,都提交到相同的地址/login/check,不过为了区分请求到底是前台登录认证还是后台登录认证,这里使用了一个名为token的请求参数来区分,当token的值为backend的时候表明是后台登录认证,当token的值为forend的时候表明是前台登录认证。
<custom-filter ref="multipleAuthenticationProcessingFilter" before="FORM_LOGIN_FILTER"/>
这段配置表明自定义的认证过滤器将在Spring Security默认的UsernamePasswordAuthenticationFilter前执行,研究UsernamePasswordAuthenticationFilter源码你就会发现平时使用到的登录认证请求地址j_spring_security_check就是被这个过滤器进行拦截并进行处理的,所以如果只是简单的登录认证,你只需要在登录页面进行一些修改就完成可以了,因为后台的处理已经完全交由Spring Security来帮我们处理了。
Spring Security 3多用户登录实现之四 用户凭证
前讲讲到AuthenticationFilter会拦截我们的登录表单提交信息并根据相应的信息构造出对应的用户凭证,这里的用户凭证将会贯穿整个Spring Security安全验证过程,如果验证用户凭证成功,我们可以为相应的用户凭证分配相应的权限,并将用户导向登录成功的界面。来看看这里的多种类型用户登录凭证的实现吧,这里主要实现了两种用户凭证,一种是前台用户登录凭证,一种是后台用户登录凭证。
- package com.template.security.authentication.token;
- import org.springframework.security.authentication.AbstractAuthenticationToken;
- import org.springframework.security.core.GrantedAuthority;
- import org.springframework.security.core.authority.SimpleGrantedAuthority;
- import java.util.ArrayList;
- import java.util.List;
- /**
- * Created by IntelliJ IDEA.
- * User: Zhong Gang
- * Date: 12-11-4
- * Time: 下午11:23
- */
- public class ForendAuthenticationToken extends AbstractAuthenticationToken {
- private String email;
- private String phone;
- public ForendAuthenticationToken(String email, String phone, List<GrantedAuthority> grantedAuthorities) {
- super(grantedAuthorities);
- this.email = email;
- this.phone = phone;
- }
- public String getEmail() {
- return email;
- }
- public String getPhone() {
- return phone;
- }
- @Override
- public Object getCredentials() {
- return null;
- }
- @Override
- public Object getPrincipal() {
- return null;
- }
- }
- package com.template.security.authentication.token;
- import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
- import org.springframework.security.core.GrantedAuthority;
- import java.util.Collection;
- /**
- * Created by IntelliJ IDEA.
- * User: Zhong Gang
- * Date: 12-11-4
- * Time: 下午11:24
- */
- public class BackendAuthenticationToken extends UsernamePasswordAuthenticationToken {
- private String captcha;
- public BackendAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities, String captcha) {
- super(principal, credentials, authorities);
- this.captcha = captcha;
- }
- public String getCaptcha() {
- return captcha;
- }
- }
为了标志我们创建的类为一个用户凭证并且能够被Spring Security识别,我们需要实现Authentication接口,因为Spring Security为我们提供了一个抽象的凭证,所以这里我的前台凭证就继承了这样一个抽象的凭证类,名为AbstractAuthenticationToken, 根据前台表单的提交信息有邮件地址和电话号码,所以实现的ForendAuthenticationToken包含这样两个属性,而Spring Security为我们提供了常见的用户名和密码的登录凭证实现,我的后台登录表单信息只是多了一个验证码,所以我直接继承了UsernamePasswordAuthenticationToken这样一个类。
Spring Security 3多用户登录实现之五 验证用户凭证
有了用户凭证后, 如何验证用户的凭证是否正确呢, 这就需要借助AuthenticationManager了, AuthenticationManager可以包含多个AuthenticationProvider, 每个AuthenticationProvider都会针对特定的AuthenticationToken, 也就是用户凭证来验证相应的用户凭证是否正确。
来看看我为了实现验证前台用户凭证和后台用户凭证而实现的AuthenticationProvider吧。
- package com.template.security.authentication.provider;
- import com.template.security.authentication.token.BackendAuthenticationToken;
- import org.springframework.security.authentication.AuthenticationProvider;
- import org.springframework.security.authentication.AuthenticationServiceException;
- import org.springframework.security.core.Authentication;
- import org.springframework.security.core.AuthenticationException;
- import org.springframework.security.core.context.SecurityContextHolder;
- /**
- * Created by IntelliJ IDEA.
- * User: Zhong Gang
- * Date: 12-11-4
- * Time: 下午11:16
- */
- public class BackendAuthenticationProvider implements AuthenticationProvider {
- @Override
- public Authentication authenticate(Authentication authentication) throws AuthenticationException {
- BackendAuthenticationToken authenticationToken = (BackendAuthenticationToken) authentication;
- // String captcha = authenticationToken.getCaptcha();
- // if (captcha.startsWith("ZZ")) {
- // throw new AuthenticationServiceException("The captcha is wrong!");
- // }
- String username = (String) authenticationToken.getPrincipal();
- String password = (String) authenticationToken.getCredentials();
- if (username.equalsIgnoreCase("ZHONGGANG") && password.equalsIgnoreCase("123")) {
- SecurityContextHolder.getContext().setAuthentication(authenticationToken);
- return authenticationToken;
- }
- throw new AuthenticationServiceException("The username or password is not correct!");
- }
- @Override
- public boolean supports(Class<?> authentication) {
- return BackendAuthenticationToken.class.isAssignableFrom(authentication);
- }
- }
- package com.template.security.authentication.provider;
- import com.template.security.authentication.token.ForendAuthenticationToken;
- import org.springframework.security.authentication.AuthenticationProvider;
- import org.springframework.security.authentication.AuthenticationServiceException;
- import org.springframework.security.core.Authentication;
- import org.springframework.security.core.AuthenticationException;
- import org.springframework.security.core.context.SecurityContextHolder;
- /**
- * Created by IntelliJ IDEA.
- * User: Zhong Gang
- * Date: 12-11-4
- * Time: 下午11:16
- */
- public class ForendAuthenticationProvider implements AuthenticationProvider {
- @Override
- public Authentication authenticate(Authentication authentication) throws AuthenticationException {
- ForendAuthenticationToken authenticationToken = (ForendAuthenticationToken) authentication;
- String email = authenticationToken.getEmail();
- String phone = authenticationToken.getPhone();
- if (email.endsWith("@qq.com") && phone.startsWith("139")) {
- authenticationToken.setAuthenticated(true);
- SecurityContextHolder.getContext().setAuthentication(authenticationToken);
- return authenticationToken;
- }
- throw new AuthenticationServiceException("The email or phone is not correct!");
- }
- @Override
- public boolean supports(Class<?> authentication) {
- return ForendAuthenticationToken.class.isAssignableFrom(authentication);
- }
- }
不论是前台用户凭证验证还是后台用户凭证验证,都实现了AuthenticationProvider接口,其中的supports方法表明这个AuthenticationProvider需要对哪个类型的用户凭证进行验证。这里我只是进行了一个简单的验证,没有什么实际意义,如果你的验证需要与数据库打交道,你可以在AuthenticationProvider中注入你的服务。来看看配置文件中的相应配置信息吧。
- <authentication-manager alias="authenticationManager">
- <authentication-provider ref="forendAuthenticationProvider"/>
- <authentication-provider ref="backendAuthenticationProvider"/>
- </authentication-manager>
- <beans:bean id="backendAuthenticationProvider"
- class="com.template.security.authentication.provider.BackendAuthenticationProvider"/>
- <beans:bean id="forendAuthenticationProvider"
- class="com.template.security.authentication.provider.ForendAuthenticationProvider"/>
Spring Security 3多用户登录实现之六 用户验证后处理
验证用户后主要有这样两种走向,一种是验证失败,一种是验证成功,验证失败后应该如何处理呢,验证成功又该如何处理呢?
验证失败的处理需要实现AuthenticationFailureHandler接口,我的前台用户认证失败的处理是这样的
- package com.template.security.authentication.handler;
- import com.template.security.shared.DirectUrlResolver;
- import org.springframework.security.core.AuthenticationException;
- import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
- import java.util.ArrayList;
- import java.util.List;
- /**
- * Created by IntelliJ IDEA.
- * User: Zhong Gang
- * Date: 12-11-9
- * Time: 下午11:20
- */
- public class MultipleAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
- private List<DirectUrlResolver> resolvers = new ArrayList<DirectUrlResolver>();
- @Override
- public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
- for (DirectUrlResolver resolver : resolvers) {
- if (resolver.support(request)) {
- String directUrl = resolver.directUrl();
- setDefaultFailureUrl(directUrl);
- }
- }
- super.onAuthenticationFailure(request, response, exception);
- }
- public void setResolvers(List<DirectUrlResolver> resolvers) {
- this.resolvers = resolvers;
- }
- }
验证成功的处理需要实现AuthenticationSuccessHandler接口,我的后台验证成功处理是这样的
- package com.template.security.authentication.handler;
- import com.template.security.shared.DirectUrlResolver;
- import org.springframework.security.core.Authentication;
- import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
- import java.util.ArrayList;
- import java.util.List;
- /**
- * Created by IntelliJ IDEA.
- * User: Zhong Gang
- * Date: 12-11-9
- * Time: 下午11:20
- */
- public class MultipleAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
- private List<DirectUrlResolver> resolvers = new ArrayList<DirectUrlResolver>();
- @Override
- public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
- for (DirectUrlResolver resolver : resolvers) {
- if (resolver.support(request)) {
- String directUrl = resolver.directUrl();
- setDefaultTargetUrl(directUrl);
- }
- }
- super.onAuthenticationSuccess(request, response, authentication);
- }
- public void setResolvers(List<DirectUrlResolver> resolvers) {
- this.resolvers = resolvers;
- }
- }
不论是前台验证成功还是后台验证成功,前台验证失败还是后台验证失败我都有不同的处理,前台验证成功导向前台验证成功界面,后台验证成功导向后台验证成功界面, 前台验证失败导向前台登录界面, 后台验证失败导向后台登录界面,所以这里我使用了前面我书写的一个通用接口,也就是DirectUrlResolver。来看看验证处理成功或失败的配置信息。
- <beans:bean id="multipleAuthenticationSuccessHandler"
- class="com.template.security.authentication.handler.MultipleAuthenticationSuccessHandler">
- <beans:property name="alwaysUseDefaultTargetUrl" value="true"/>
- <beans:property name="resolvers">
- <beans:list>
- <beans:ref bean="backendAuthenticationSuccessUrlResolver"/>
- <beans:ref bean="forendAuthenticationSuccessUrlResolver"/>
- </beans:list>
- </beans:property>
- </beans:bean>
- <beans:bean id="backendAuthenticationSuccessUrlResolver"
- class="com.template.security.shared.RequestParameterDirectUrlResolver">
- <beans:property name="parameterName" value="token"/>
- <beans:property name="pattern" value="backend"/>
- <beans:property name="directUrl" value="/backend/login/success"/>
- </beans:bean>
- <beans:bean id="forendAuthenticationSuccessUrlResolver"
- class="com.template.security.shared.RequestParameterDirectUrlResolver">
- <beans:property name="parameterName" value="token"/>
- <beans:property name="pattern" value="forend"/>
- <beans:property name="directUrl" value="/forend/login/success"/>
- </beans:bean>
- <beans:bean id="multipleAuthenticationFailureHandler"
- class="com.template.security.authentication.handler.MultipleAuthenticationFailureHandler">
- <beans:property name="resolvers">
- <beans:list>
- <beans:ref bean="backendAuthenticationFailureUrlResolver"/>
- <beans:ref bean="forendAuthenticationFailureUrlResolver"/>
- </beans:list>
- </beans:property>
- </beans:bean>
- <beans:bean id="backendAuthenticationFailureUrlResolver"
- class="com.template.security.shared.RequestParameterDirectUrlResolver">
- <beans:property name="parameterName" value="token"/>
- <beans:property name="pattern" value="backend"/>
- <beans:property name="directUrl" value="/backend/login?error=1"/>
- </beans:bean>
- <beans:bean id="forendAuthenticationFailureUrlResolver"
- class="com.template.security.shared.RequestParameterDirectUrlResolver">
- <beans:property name="parameterName" value="token"/>
- <beans:property name="pattern" value="forend"/>
- <beans:property name="directUrl" value="/forend/login?error=1"/>
- </beans:bean>
这里还需要将相应的验证Handler注入到前讲的认证处理Filter中。