spring security进级篇VI JCaptcha验证编码的使用
在spring security中,可以结合jcaptcha进行使用,具体方法如下:
1.java类如下:
package com.spring.security.jcaptcha;import java.awt.Color;import java.awt.Font;import java.awt.image.ImageFilter;import com.octo.captcha.component.image.backgroundgenerator.BackgroundGenerator;import com.octo.captcha.component.image.backgroundgenerator.UniColorBackgroundGenerator;import com.octo.captcha.component.image.color.RandomListColorGenerator;import com.octo.captcha.component.image.deformation.ImageDeformation;import com.octo.captcha.component.image.deformation.ImageDeformationByFilters;import com.octo.captcha.component.image.fontgenerator.FontGenerator;import com.octo.captcha.component.image.fontgenerator.RandomFontGenerator;import com.octo.captcha.component.image.textpaster.DecoratedRandomTextPaster;import com.octo.captcha.component.image.textpaster.TextPaster;import com.octo.captcha.component.image.textpaster.textdecorator.TextDecorator;import com.octo.captcha.component.image.wordtoimage.DeformedComposedWordToImage;import com.octo.captcha.component.image.wordtoimage.WordToImage;import com.octo.captcha.component.word.FileDictionary;import com.octo.captcha.component.word.wordgenerator.ComposeDictionaryWordGenerator;import com.octo.captcha.component.word.wordgenerator.WordGenerator;import com.octo.captcha.engine.image.ListImageCaptchaEngine;import com.octo.captcha.image.gimpy.GimpyFactory;/** * JCaptcha验证码图片生成引擎, 仿照JCaptcha2.0编写类似GMail验证码的样式. */public class GMailEngine extends ListImageCaptchaEngine {@Overrideprotected void buildInitialFactories() {// 图片和字体大小设置int minWordLength = 4;int maxWordLength = 5;int fontSize = 20;int imageWidth = 100;int imageHeight = 36;WordGenerator dictionnaryWords = new ComposeDictionaryWordGenerator(new FileDictionary("toddlist"));// word2image componentsTextPaster randomPaster = new DecoratedRandomTextPaster(minWordLength,maxWordLength, new RandomListColorGenerator(new Color[] {new Color(23, 170, 27), new Color(220, 34, 11),new Color(23, 67, 172) }), new TextDecorator[] {});BackgroundGenerator background = new UniColorBackgroundGenerator(imageWidth, imageHeight, Color.white);FontGenerator font = new RandomFontGenerator(fontSize, fontSize,new Font[] { new Font("nyala", Font.BOLD, fontSize),new Font("Bell MT", Font.PLAIN, fontSize),new Font("Credit valley", Font.BOLD, fontSize) });ImageDeformation postDef = new ImageDeformationByFilters(new ImageFilter[] {});ImageDeformation backDef = new ImageDeformationByFilters(new ImageFilter[] {});ImageDeformation textDef = new ImageDeformationByFilters(new ImageFilter[] {});WordToImage word2image = new DeformedComposedWordToImage(font,background, randomPaster, backDef, textDef, postDef);addFactory(new GimpyFactory(dictionnaryWords, word2image));}}?
过滤器如下:
package com.spring.security.jcaptcha;import java.awt.image.BufferedImage;import java.io.IOException;import javax.imageio.ImageIO;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletOutputStream;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.commons.lang.StringUtils;import org.apache.log4j.Logger;import org.springframework.context.ApplicationContext;import org.springframework.web.context.support.WebApplicationContextUtils;import com.octo.captcha.service.CaptchaService;import com.octo.captcha.service.CaptchaServiceException;/** * 针对 JCaptcha 专门的过滤器(Filter) * */public class JCaptchaFilter implements Filter {// web.xml中的参数名定义public static final String PARAM_CAPTCHA_PARAMTER_NAME = "captchaParamterName";public static final String PARAM_CAPTCHA_SERVICE_ID = "captchaServiceId";public static final String PARAM_FILTER_PROCESSES_URL = "filterProcessesUrl";public static final String PARAM_FAILURE_URL = "failureUrl";public static final String PARAM_AUTO_PASS_VALUE = "autoPassValue";// 默认值定义public static final String DEFAULT_FILTER_PROCESSES_URL = "/j_spring_security_check";public static final String DEFAULT_CAPTCHA_SERVICE_ID = "captchaService";public static final String DEFAULT_CAPTCHA_PARAMTER_NAME = "j_captcha";protected static Logger logger = Logger.getLogger("service");private String failureUrl;private String filterProcessesUrl = DEFAULT_FILTER_PROCESSES_URL;private String captchaServiceId = DEFAULT_CAPTCHA_SERVICE_ID;private String captchaParamterName = DEFAULT_CAPTCHA_PARAMTER_NAME;private String autoPassValue;private CaptchaService captchaService;/** * Filter回调初始化函数. */public void init(FilterConfig filterConfig) throws ServletException {// TODO Auto-generated method stubinitParameters(filterConfig);initCaptchaService(filterConfig);}public void doFilter(ServletRequest theRequest,ServletResponse theResponse, FilterChain chain) throws IOException,ServletException {HttpServletRequest request = (HttpServletRequest) theRequest;HttpServletResponse response = (HttpServletResponse) theResponse;String servletPath = request.getServletPath();// 符合filterProcessesUrl为验证处理请求,其余为生成验证图片请求.if (StringUtils.startsWith(servletPath, filterProcessesUrl)) {boolean validated = validateCaptchaChallenge(request);if (validated) {chain.doFilter(request, response);} else {redirectFailureUrl(request, response);}} else {genernateCaptchaImage(request, response);}}/** * Filter回调退出函数. */public void destroy() {// TODO Auto-generated method stub}/** * 初始化web.xml中定义的filter init-param. */protected void initParameters(final FilterConfig fConfig) {if (StringUtils.isBlank(fConfig.getInitParameter(PARAM_FAILURE_URL))) {throw new IllegalArgumentException("CaptchaFilter缺少failureUrl参数");}failureUrl = fConfig.getInitParameter(PARAM_FAILURE_URL);if (StringUtils.isNotBlank(fConfig.getInitParameter(PARAM_FILTER_PROCESSES_URL))) {filterProcessesUrl = fConfig.getInitParameter(PARAM_FILTER_PROCESSES_URL);}if (StringUtils.isNotBlank(fConfig.getInitParameter(PARAM_CAPTCHA_SERVICE_ID))) {captchaServiceId = fConfig.getInitParameter(PARAM_CAPTCHA_SERVICE_ID);}if (StringUtils.isNotBlank(fConfig.getInitParameter(PARAM_CAPTCHA_PARAMTER_NAME))) {captchaParamterName = fConfig.getInitParameter(PARAM_CAPTCHA_PARAMTER_NAME);}if (StringUtils.isNotBlank(fConfig.getInitParameter(PARAM_AUTO_PASS_VALUE))) {autoPassValue = fConfig.getInitParameter(PARAM_AUTO_PASS_VALUE);}}/** * 从ApplicatonContext获取CaptchaService实例. */protected void initCaptchaService(final FilterConfig fConfig) {ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(fConfig.getServletContext());captchaService = (CaptchaService) context.getBean(captchaServiceId);}/** * 生成验证码图片. */protected void genernateCaptchaImage(final HttpServletRequest request,final HttpServletResponse response) throws IOException {setDisableCacheHeader(response);response.setContentType("image/jpeg");ServletOutputStream out = response.getOutputStream();try {String captchaId = request.getSession(true).getId();BufferedImage challenge = (BufferedImage) captchaService.getChallengeForID(captchaId, request.getLocale());ImageIO.write(challenge, "jpg", out);out.flush();} catch (CaptchaServiceException e) {logger.error(e.getMessage(), e);} finally {if(out!=null){out.close();}}}/** * 验证验证码. */protected boolean validateCaptchaChallenge(final HttpServletRequest request) {try {String captchaID = request.getSession().getId();String challengeResponse = request.getParameter(captchaParamterName);// 自动通过值存在时,检验输入值是否等于自动通过值if (StringUtils.isNotBlank(autoPassValue)&& autoPassValue.equals(challengeResponse)) {return true;}return captchaService.validateResponseForID(captchaID,challengeResponse);} catch (CaptchaServiceException e) {logger.error(e.getMessage(), e);return false;}}/** * 跳转到失败页面. * * 可在子类进行扩展, 比如在session中放入SpringSecurity的Exception. */protected void redirectFailureUrl(final HttpServletRequest request,final HttpServletResponse response) throws IOException {response.sendRedirect(request.getContextPath() + failureUrl);}/** * 设置禁止客户端缓存的Header. */public static void setDisableCacheHeader(HttpServletResponse response) {// Http 1.0 headerresponse.setDateHeader("Expires", 1L);response.addHeader("Pragma", "no-cache");// Http 1.1 headerresponse.setHeader("Cache-Control", "no-cache, no-store, max-age=0");}}?
web.xml 配置如下:
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>springSecurityIII</display-name> <!--******************************** --><!--*******log4j日志信息的配置****** --><!--******************************* --><context-param><param-name>log4jConfigLocation</param-name><param-value>classpath:log4j.xml</param-value></context-param><!--Spring默认刷新Log4j配置文件的间隔,单位为millisecond,可以不设置 --><context-param><param-name>log4jRefreshInterval</param-name><param-value>60000</param-value></context-param><!--******************************** --><!--*******spring bean的配置******** --><!--******************************* --><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext.xml</param-value></context-param><listener><listener-class>org.springframework.web.util.Log4jConfigListener</listener-class></listener><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><listener><listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class></listener><!--******************************** --><!--*******字符集 过滤器************ --><!--******************************* --><filter><filter-name>CharacterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param><init-param><param-name>forceEncoding</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>CharacterEncodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><!--******************************** --><!--*******session的配置************ --><!--******************************* --><session-config><session-timeout>30</session-timeout></session-config> <filter> <filter-name>jcaptchaFilter</filter-name> <filter-class>com.spring.security.jcaptcha.JCaptchaFilter</filter-class> <init-param> <param-name>failureUrl</param-name> <param-value>/login.jsp</param-value> </init-param> </filter> <filter-mapping> <filter-name>jcaptchaFilter</filter-name> <url-pattern>/jcaptcha.jpg</url-pattern> </filter-mapping> <filter-mapping> <filter-name>jcaptchaFilter</filter-name> <url-pattern>/j_spring_security_check</url-pattern> </filter-mapping> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <listener> <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class> </listener> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list></web-app>
?
login.jsp
?
<%@ include file="/common/taglibs.jsp"%><%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>登 录</title><script type="text/javascript">/*==============================================*refreash the captcha to general new picture*==============================================*/function refreshCaptcha() { $('#captchaImg').hide().attr( 'src', '<c:url value="/jcaptcha.jpg"/>' + '?' + Math.floor(Math.random() * 100)).fadeIn(); }</script></head><body><center><div method="post"><table style="width: 60%"><tr><td>用户名:</td><td><input class = "login-smallInput" type='text' name='j_username'/></td></tr><tr><td>密 码:</td><td><input class = "login-smallInput" type='password' name='j_password' /></td></tr><tr><td>验证码:</td><td><input type='text' name='j_captcha' size="5"/> <img id="captchaImg" style="vertical-align:middle" src="<c:url value="/jcaptcha.jpg"/>" /> <a href="javascript:refreshCaptcha()">看不清楚换一张</a></td></tr><tr><td><input id="_spring_security_remember_me" name="_spring_security_remember_me" type="checkbox"/></td><td><label for="_spring_security_remember_me">Remember Me?</label></td></tr><tr><td colspan="2"><input type="submit" name="submit" value="登录" /></td></tr></table></form></center></body></html>?