package cc.bnblogs.springsecurity.validate.imagecode; import cc.bnblogs.springsecurity.Exception.ValidateCodeException; import cc.bnblogs.springsecurity.controller.ValidateCodeController; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.social.connect.web.HttpSessionSessionStrategy; import org.springframework.social.connect.web.SessionStrategy; import org.springframework.stereotype.Component; import org.springframework.web.bind.ServletRequestBindingException; import org.springframework.web.bind.ServletRequestUtils; import org.springframework.web.context.request.ServletWebRequest; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * 本过滤器只会校验一次 */ @Component public class ValidateCodeFilter extends OncePerRequestFilter { @Autowired private AuthenticationFailureHandler authenticationFailureHandler; private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy(); @Override protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException { // 判断请求的路径和方法决定是否进行验证码校验 if (StringUtils.equalsIgnoreCase("/login", httpServletRequest.getRequestURI()) && StringUtils.equalsIgnoreCase(httpServletRequest.getMethod(), "post")) { try { validateCode(new ServletWebRequest(httpServletRequest)); } catch (ValidateCodeException e) { // 校验失败,返回对应错误信息 authenticationFailureHandler.onAuthenticationFailure(httpServletRequest, httpServletResponse, e); return; } } // 不需要进行验证码校验,进入下一步 filterChain.doFilter(httpServletRequest, httpServletResponse); } /** * 验证码校验 * @param servletWebRequest * @throws ServletRequestBindingException */ private void validateCode(ServletWebRequest servletWebRequest) throws ServletRequestBindingException { // 从Session中取出ImageCode对象 ImageCode codeInSession = (ImageCode) sessionStrategy.getAttribute(servletWebRequest, ValidateCodeController.SESSION_KEY_IMAGE_CODE); // 获取用户输入的验证码 String codeInRequest = ServletRequestUtils.getStringParameter(servletWebRequest. getRequest(), "imageCode"); if (StringUtils.isBlank(codeInRequest)) { throw new ValidateCodeException("验证码不能为空!"); } if (codeInSession == null) { throw new ValidateCodeException("验证码不存在!"); } if (codeInSession.isExpire()) { sessionStrategy.removeAttribute(servletWebRequest, ValidateCodeController.SESSION_KEY_IMAGE_CODE); throw new ValidateCodeException("验证码已过期!"); } if (!StringUtils.equalsIgnoreCase(codeInSession.getCode(), codeInRequest)) { throw new ValidateCodeException("验证码不正确!"); } // 从Session中移除验证码对象 sessionStrategy.removeAttribute(servletWebRequest, ValidateCodeController.SESSION_KEY_IMAGE_CODE); } }