`
x_root
  • 浏览: 125483 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Spring security2.0增加验证码功能

    博客分类:
  • Java
阅读更多

做权限控制的时候用了spring security2.0,但是后来又增加了登录页面需要验证码功能,想了一下,实现如下:

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.security.AuthenticationException;
import org.springframework.security.SpringSecurityMessageSource;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.ui.FilterChainOrder;
import org.springframework.security.ui.SpringSecurityFilter;
import org.springframework.security.util.RedirectUtils;
import org.springframework.security.util.UrlUtils;
import org.springframework.util.Assert;

/**
 * 加入了验证码的过滤器
 * 
 * @author Alfoo Liu <liuxy2@xxx.com>
 * @since 2010-1-7 10:28:35
 */
public class AuthenticationCodeFilter extends SpringSecurityFilter implements InitializingBean, MessageSourceAware {
	public final static String SPRING_SECURITY_FORM_AUTHCODE_KEY = "j_authCode";
	private final static String AUTHCODE_KEY_IN_SESSION = "AUTHCODE";
	public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "j_username";
	public static final String SPRING_SECURITY_LAST_USERNAME_KEY = "SPRING_SECURITY_LAST_USERNAME";
	public static final String SPRING_SECURITY_LAST_EXCEPTION_KEY = "SPRING_SECURITY_LAST_EXCEPTION";
	private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
	private String authCodeParameter = SPRING_SECURITY_FORM_AUTHCODE_KEY;
	private String authenticationFailureUrl = "/login.dm?error=true";
	private boolean enableAuthCode = true;
	private final static Log log = LogFactory
			.getLog(AuthenticationCodeFilter.class);
	protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
	private boolean useRelativeContext = false;
	private String filterProcessesUrl = "/j_spring_security_check";
	
	@Override
	public void doFilterHttp(HttpServletRequest request,
			HttpServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// Place the last username attempted into HttpSession for views
		HttpSession session = request.getSession();
		// boolean s = session != null || getAllowSessionCreation();
		// 获取页面传过来的验证码值
		String authCode = this.obtainAuthCode(request);
		String username = obtainUsername(request);
		log.debug("auth code = " + authCode);
		if (enableAuthCode && requiresAuthentication(request, response)) {
			if (authCode == null || authCode.trim().length() == 0) {
				log.error("validate authcode failed, auth code is null.");
				session.setAttribute(SPRING_SECURITY_LAST_USERNAME_KEY,
						username);
				
				AuthenticationException exception = new AuthenticationCodeErrorException(
						messages
								.getMessage(
										"AbstractUserDetailsAuthenticationProvider.empty_authcode",
										"Please input authcode."));// "验证码不能为空。"
				unsuccessfulAuthentication(request, response, exception);
				return;
			}

			String expected = (String) session
					.getAttribute(AUTHCODE_KEY_IN_SESSION);
			if (!authCode.equals(expected)) {// AuthCodeValidationException
				session.setAttribute(SPRING_SECURITY_LAST_USERNAME_KEY,
						username);
				AuthenticationException exception = new AuthenticationCodeErrorException(
						messages
								.getMessage(
										"AbstractUserDetailsAuthenticationProvider.error_authcode",
										"authcode is error."));
				unsuccessfulAuthentication(request, response, exception);
				return;
			}
		}
		
		
		chain.doFilter(request, response);
	}

	protected void unsuccessfulAuthentication(HttpServletRequest request,
			HttpServletResponse response, AuthenticationException failed)
			throws IOException, ServletException {
		SecurityContextHolder.getContext().setAuthentication(null);

		if (logger.isDebugEnabled()) {
			logger
					.debug("Updated SecurityContextHolder to contain null Authentication");
		}

		request.getSession().setAttribute(
				SPRING_SECURITY_LAST_EXCEPTION_KEY, failed);

		if (authenticationFailureUrl == null) {
			response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
					"Authentication Failed:" + failed.getMessage());
		} else {
			sendRedirect(request, response, authenticationFailureUrl);
		}
	}

    protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
        String uri = request.getRequestURI();
        int pathParamIndex = uri.indexOf(';');

        if (pathParamIndex > 0) {
            // strip everything after the first semi-colon
            uri = uri.substring(0, pathParamIndex);
        }

        if ("".equals(request.getContextPath())) {
            return uri.endsWith(filterProcessesUrl);
        }

        return uri.endsWith(request.getContextPath() + filterProcessesUrl);
    }
    
    
	protected void sendRedirect(HttpServletRequest request,
			HttpServletResponse response, String url) throws IOException {

		RedirectUtils.sendRedirect(request, response, url, useRelativeContext);
	}

	public int getOrder() {
		return FilterChainOrder.AUTHENTICATION_PROCESSING_FILTER - 100;
	}

	protected String obtainAuthCode(HttpServletRequest request) {
		return request.getParameter(getAuthCodeParameter());
	}

	protected String obtainUsername(HttpServletRequest request) {
		return request.getParameter(usernameParameter);
	}

	public boolean isEnableAuthCode() {
		return enableAuthCode;
	}

	public void setEnableAuthCode(boolean enableAuthCode) {
		this.enableAuthCode = enableAuthCode;
	}

	public String getAuthCodeParameter() {
		return authCodeParameter;
	}

	public void setAuthCodeParameter(String authCodeParameter) {
		this.authCodeParameter = authCodeParameter;
	}

	public String getAuthenticationFailureUrl() {
		return authenticationFailureUrl;
	}

	public void setAuthenticationFailureUrl(String authenticationFailureUrl) {
		this.authenticationFailureUrl = authenticationFailureUrl;
	}
	
    public void setUseRelativeContext(boolean useRelativeContext) {
        this.useRelativeContext = useRelativeContext;
    }

	public void afterPropertiesSet() throws Exception {
		Assert.isTrue(UrlUtils.isValidRedirectUrl(authenticationFailureUrl), authenticationFailureUrl + " isn't a valid redirect URL");
	}

	public void setMessageSource(MessageSource messageSource) {
		this.messages = new MessageSourceAccessor(messageSource);
	}
}

 

applicationContext-security.xml配置如下:

<beans:bean id="authenticationProcessingFilter" class="com.asiainfo.webframe.core.security.AuthenticationCodeFilter">
	<custom-filter before="AUTHENTICATION_PROCESSING_FILTER" />
	<!--以下两项的配置应该要和form-login的配置相同-->
	<beans:property name="authenticationFailureUrl" value="/login.dm?error=true" />
</beans:bean>

 

http的配置仍然是auto-config="true"。

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics