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);
    }
}
扫描二维码关注公众号,回复: 791254 查看本文章
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来帮我们处理了。

猜你喜欢

转载自dreamzhong.iteye.com/blog/1722280