读书人

Spring security2.0增多验证码功能

发布时间: 2012-10-13 11:38:17 作者: rapoo

Spring security2.0增加验证码功能

做权限控制的时候用了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";@Overridepublic void doFilterHttp(HttpServletRequest request,HttpServletResponse response, FilterChain chain)throws IOException, ServletException {// Place the last username attempted into HttpSession for viewsHttpSession 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)) {// AuthCodeValidationExceptionsession.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" /><!--以下两项的配置应该要和form-login的配置相同--><beans:property name="authenticationFailureUrl" value="/login.dm?error=true" /></beans:bean>

?

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

?

读书人网 >软件架构设计

热点推荐