1、从jcaptcha官方网站下载jcaptcha的发行包,并将其发行包中的jar文件考贝到本地项目WEB-INF目录下的lib目录中。
官方网址http://jcaptcha.sourceforge.net/
2、在web.xml文件中配置
<servlet> <servlet-name>jcaptcha</servlet-name> <servlet-class>cn.hxex.order.core.jcaptcha.ImageCaptchaServlet</servlet-class> <load-on-startup>3</load-on-startup> </servlet> <servlet-mapping> <servlet-name>jcaptcha</servlet-name> <url-pattern>/captcha.jpg</url-pattern> </servlet-mapping>
3、jcaptcha在spring中的配置
<bean id="channelProcessingFilter" class="org.acegisecurity.securechannel.ChannelProcessingFilter"> <property name="channelDecisionManager"> <ref local="channelDecisionManager"/> </property> <property name="filterInvocationDefinitionSource"> <value> CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /j_security_check=REQUIRES_CAPTCHA_ONCE_ABOVE_THRESOLD_REQUESTS </value> </property> </bean> <bean id="channelDecisionManager" class="org.acegisecurity.securechannel.ChannelDecisionManagerImpl"> <property name="channelProcessors"> <list> <ref local="testOnceAfterMaxRequestsCaptchaChannelProcessor"/> <ref local="alwaysTestAfterTimeInMillisCaptchaChannelProcessor"/> <ref local="alwaysTestAfterMaxRequestsCaptchaChannelProcessor"/> <ref local="alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor"/> </list> </property> </bean> <!-- REQUIRES_CAPTCHA_ONCE_ABOVE_THRESOLD_REQUESTS --> <bean id="testOnceAfterMaxRequestsCaptchaChannelProcessor" class="org.acegisecurity.captcha.TestOnceAfterMaxRequestsCaptchaChannelProcessor"> <property name="thresold"> <value>0</value> </property> <property name="entryPoint"> <ref bean="captchaEntryPoint"/> </property> </bean> <!-- REQUIRES_CAPTCHA_ABOVE_THRESOLD_REQUESTS --> <bean id="alwaysTestAfterMaxRequestsCaptchaChannelProcessor" class="org.acegisecurity.captcha.AlwaysTestAfterMaxRequestsCaptchaChannelProcessor"> <property name="thresold"> <value>5</value> </property> <property name="entryPoint"> <ref bean="captchaEntryPoint"/> </property> </bean> <!-- REQUIRES_CAPTCHA_AFTER_THRESOLD_IN_MILLIS --> <bean id="alwaysTestAfterTimeInMillisCaptchaChannelProcessor" class="org.acegisecurity.captcha.AlwaysTestAfterTimeInMillisCaptchaChannelProcessor"> <property name="thresold"> <value>5000</value> </property> <property name="entryPoint"> <ref bean="captchaEntryPoint"/> </property> </bean> <!-- REQUIRES_CAPTCHA_BELOW_AVERAGE_TIME_IN_MILLIS_REQUESTS --> <bean id="alwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor" class="org.acegisecurity.captcha.AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor"> <property name="thresold"> <value>20000</value> </property> <property name="entryPoint"> <ref bean="captchaEntryPoint"/> </property> </bean> <bean id="captchaEntryPoint" class="org.acegisecurity.captcha.CaptchaEntryPoint"> <!--验证码验证失败后转向的页面!--> <property name="captchaFormUrl"> <value>/admin/login.jsp?login_error=code_error</value> </property> <property name="includeOriginalRequest"> <value>false</value> </property> <property name="includeOriginalParameters"> <value>false</value> </property> </bean> <bean id="captchaValidationProcessingFilter" class="org.acegisecurity.captcha.CaptchaValidationProcessingFilter"> <property name="captchaService"> <ref bean="captchaService"/> </property> <property name="captchaValidationParameter" value="j_captcha_response"/> </bean> <!-- imageCaptchaService is injected into captchaImageCreateController as well as to captchaService beans --> <!--自己定义的实体类(注意路径!!)--> <bean id="captchaService" class="cn.hxex.order.core.jcaptcha.JCaptchaServiceProxyImpl"> <property name="jcaptchaService" ref="imageCaptchaService"/> </bean> <bean id="imageCaptchaService" class="com.octo.captcha.service.image.DefaultManageableImageCaptchaService"> <constructor-arg type="com.octo.captcha.service.captchastore.CaptchaStore" index="0"> <ref bean="fastHashMapCaptchaStore"/> </constructor-arg> <!-- (1) which captcha Engine you use --> <constructor-arg type="com.octo.captcha.engine.CaptchaEngine" index="1"> <ref bean="captchaEngineEx"/> </constructor-arg> <constructor-arg index="2"> <value>180</value> </constructor-arg> <constructor-arg index="3"> <value>100000</value> </constructor-arg> <constructor-arg index="4"> <value>75000</value> </constructor-arg> </bean> <bean id="fastHashMapCaptchaStore" class="com.octo.captcha.service.captchastore.FastHashMapCaptchaStore"/> <!-- (2) you can define more than one captcha engine here --> <bean id="captchaEngineEx" class="cn.hxex.order.core.jcaptcha.engine.CaptchaEngineEx"> </bean> <bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy"> <property name="filterInvocationDefinitionSource"> <value> CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /**=httpSessionContextIntegrationFilter,captchaValidationProcessingFilter,channelProcessingFilter,authenticationProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor </value> </property> </bean> <bean id="httpSessionContextIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter"> <!-- 将下面的property注释掉,验证码将无效!!! --> <property name="context"> <value> org.acegisecurity.captcha.CaptchaSecurityContextImpl </value> </property> </bean>
·············省略了一些spring安全框架的bean,自己加去吧
4、编写jcaptcha的实体类
实体类包的路径一定要和spring配置文件里的路径一样
(1)CaptchaEngine 类
package cn.hxex.order.core.jcaptcha.engine; import java.awt.Color; import com.octo.captcha.component.image.backgroundgenerator.BackgroundGenerator; import com.octo.captcha.component.image.backgroundgenerator .FunkyBackgroundGenerator; import com.octo.captcha.component.image.fontgenerator.FontGenerator; import com.octo.captcha.component.image.fontgenerator .TwistedAndShearedRandomFontGenerator; import com.octo.captcha.component.image.textpaster.RandomTextPaster; import com.octo.captcha.component.image.textpaster.TextPaster; import com.octo.captcha.component.image.wordtoimage.ComposedWordToImage; import com.octo.captcha.component.image.wordtoimage.WordToImage; import com.octo.captcha.component.word.wordgenerator.RandomWordGenerator; import com.octo.captcha.component.word.wordgenerator.WordGenerator; import com.octo.captcha.engine.image.ListImageCaptchaEngine; import com.octo.captcha.image.gimpy.GimpyFactory; /** * SpringSide Custom的认证图片 * * @author cac */ public class CaptchaEngine extends ListImageCaptchaEngine { /** * @see ListImageCaptchaEngine */ protected void buildInitialFactories() { WordGenerator wordGenerator = new RandomWordGenerator("023456789"); // nteger minAcceptedWordLength, Integer maxAcceptedWordLength,Color[] // textColors TextPaster textPaster = new RandomTextPaster(4,5, Color.WHITE); // Integer width, Integer height BackgroundGenerator backgroundGenerator = new FunkyBackgroundGenerator(100,40); // Integer minFontSize, Integer maxFontSize FontGenerator fontGenerator = new TwistedAndShearedRandomFontGenerator(20, 22); WordToImage wordToImage = new ComposedWordToImage(fontGenerator, backgroundGenerator, textPaster); addFactory(new GimpyFactory(wordGenerator, wordToImage)); } }
(2)CaptchaEngineEx 类
package cn.hxex.order.core.jcaptcha.engine; import java.awt.Color; import com.octo.captcha.component.image.backgroundgenerator.BackgroundGenerator; import com.octo.captcha.component.image.backgroundgenerator .GradientBackgroundGenerator; import com.octo.captcha.component.image.color.SingleColorGenerator; 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 .BaffleTextDecorator; import com.octo.captcha.component.image.textpaster.textdecorator .LineTextDecorator; import com.octo.captcha.component.image.textpaster.textdecorator.TextDecorator; import com.octo.captcha.component.image.wordtoimage.ComposedWordToImage; import com.octo.captcha.component.image.wordtoimage.WordToImage; import com.octo.captcha.component.word.wordgenerator.RandomWordGenerator; import com.octo.captcha.component.word.wordgenerator.WordGenerator; import com.octo.captcha.engine.image.ListImageCaptchaEngine; import com.octo.captcha.image.gimpy.GimpyFactory; /** * Captcha增强版本 * * @author david.turing@gmail.com * @modifyTime 21:01:52 * @description * <pre> * 安装 Captcha Instruction <br> * 1.add captchaValidationProcessingFilter * to applicationContext-acegi-security.xml<br> * 2.modify applicationContext-captcha-security.xml * <ul> * <li> make sure that captchaValidationProcessingFilter Call captchaService <li> config CaptchaEngine for captchaService (refer imageCaptchaService) <li> write your own CaptchaEngine <li> config the following, so that We use CaptchaEngineEx to generate the captcha image. </ul> <constructor-arg * type="com.octo.captcha.engine.CaptchaEngine" index="1"> * <ref bean="captchaEngineEx"/gt; </constructor-arg> * </pre> */ public class CaptchaEngineEx extends ListImageCaptchaEngine { /** * ... */ protected void buildInitialFactories() { //Set Captcha Word Length Limitation which should not over 6 Integer minAcceptedWordLength = new Integer(4); Integer maxAcceptedWordLength = new Integer(5); //Set up Captcha Image Size: Height and Width Integer imageHeight = new Integer(40); Integer imageWidth = new Integer(100); //Set Captcha Font Size Integer minFontSize = new Integer(20); Integer maxFontSize = new Integer(22); //We just generate digit for captcha source char Although you can use //abcdefg......xyz WordGenerator wordGenerator = new RandomWordGenerator("023456789"); //cyt and unruledboy proved that backgroup not a factor of Security. A //captcha attacker won't affaid colorful backgroud, so we just use white //color, like google and hotmail. BackgroundGenerator backgroundGenerator = new GradientBackgroundGenerator( imageWidth, imageHeight, Color.white, Color.white); //font is not helpful for security but it really increase difficultness for //attacker FontGenerator fontGenerator = new RandomFontGenerator(minFontSize, maxFontSize); // Note that our captcha color is Blue SingleColorGenerator scg = new SingleColorGenerator(Color.blue); //decorator is very useful pretend captcha attack. we use two line text //decorators. LineTextDecorator lineDecorator = new LineTextDecorator(1, Color.blue); // LineTextDecorator line_decorator2 = new LineTextDecorator(1, Color.blue); TextDecorator[] textdecorators = new TextDecorator[1]; textdecorators[0] = lineDecorator; // textdecorators[1] = line_decorator2; TextPaster textPaster = new DecoratedRandomTextPaster( minAcceptedWordLength, maxAcceptedWordLength, scg, new TextDecorator[] { new BaffleTextDecorator(new Integer(1), Color.white) }); //ok, generate the WordToImage Object for logon service to use. WordToImage wordToImage = new ComposedWordToImage( fontGenerator, backgroundGenerator, textPaster); addFactory(new GimpyFactory(wordGenerator, wordToImage)); } }
(3)ImageCaptchaServlet 类
package cn.hxex.order.core.jcaptcha; import com.octo.captcha.service.CaptchaServiceException; import com.octo.captcha.service.image.ImageCaptchaService; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGImageEncoder; import org.apache.commons.lang.StringUtils; import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; /** * Servlet generates CAPTCHA jpeg images based on the JCAPTCHA package. It's * configured via spring, and requires a ImageCaptchaService bean with the * id=imageCaptchaService * 基于JCAPTCHA生成CAPTCHA jpeg图片的Servlet。它通过Spring进行配置,并且set一个 * 类型为ImageCaptchaService,id为imageCaptchaService的bean * @author Jason Thrasher */ @SuppressWarnings("serial") public class ImageCaptchaServlet extends HttpServlet { /** * Captcha Service Name */ private String captchaServiceName = "imageCaptchaService"; /** * @see HttpServlet#init(ServletConfig) */ public void init(ServletConfig servletConfig) throws ServletException { if (StringUtils.isNotBlank(servletConfig .getInitParameter("captchaServiceName"))) { captchaServiceName = servletConfig.getInitParameter("captchaServiceName"); } super.init(servletConfig); } /** * @see HttpServlet#doGet() */ protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException { byte[] captchaChallengeAsJpeg = null; // the output stream to render the captcha image as jpeg into ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream(); try { // get the image captcha service defined via the SpringFramework ApplicationContext ctx = WebApplicationContextUtils .getRequiredWebApplicationContext(getServletContext()); Object bean = ctx.getBean(captchaServiceName); ImageCaptchaService imageCaptchaService = (ImageCaptchaService) bean; // get the session id that will identify the generated captcha. // the same id must be used to validate the response, the session id // is a good candidate! String captchaId = httpServletRequest.getSession().getId(); // call the ImageCaptchaService getChallenge method BufferedImage challenge = imageCaptchaService.getImageChallengeForID( captchaId, httpServletRequest.getLocale()); // a jpeg encoder JPEGImageEncoder jpegEncoder = JPEGCodec .createJPEGEncoder(jpegOutputStream); jpegEncoder.encode(challenge); } catch (IllegalArgumentException e) { httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND); return; } catch (CaptchaServiceException e) { httpServletResponse .sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return; } captchaChallengeAsJpeg = jpegOutputStream.toByteArray(); // flush it in the response httpServletResponse.setHeader("Cache-Control", "no-store"); httpServletResponse.setHeader("Pragma", "no-cache"); httpServletResponse.setDateHeader("Expires", 0); httpServletResponse.setContentType("image/jpeg"); ServletOutputStream responseOutputStream = httpServletResponse .getOutputStream(); responseOutputStream.write(captchaChallengeAsJpeg); responseOutputStream.flush(); responseOutputStream.close(); } }
(4)JCaptchaServiceProxyImpl 类
package cn.hxex.order.core.jcaptcha; import com.octo.captcha.service.CaptchaService; import com.octo.captcha.service.CaptchaServiceException; import org.acegisecurity.captcha.CaptchaServiceProxy; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * 实现 CaptchaServiceProxy 用于acegi来校验,由spring注入jcaptchaService * * @author sshwsfc@gmail.com */ public class JCaptchaServiceProxyImpl implements CaptchaServiceProxy { /** * Log for the class */ protected static Log log = LogFactory.getLog(JCaptchaServiceProxyImpl.class); /** * instance of CaptchaService. */ private CaptchaService jcaptchaService; /** * @see {@link CaptchaServiceProxy#validateReponseForId(String, Object)} */ public boolean validateReponseForId(String id, Object response) { log.debug("validating captcha response"); try { boolean isHuman = jcaptchaService.validateResponseForID(id, response) .booleanValue(); if (isHuman) { log.debug("captcha passed"); } else { log.warn("captcha failed"); } return isHuman; } catch (CaptchaServiceException cse) { // fixes known bug in JCaptcha log.warn("captcha validation failed due to exception", cse); return false; } } public void setJcaptchaService(CaptchaService jcaptchaService) { this.jcaptchaService = jcaptchaService; } }
相关资源:Spring+SpringMVC+Mybatis框架整合例子(SSM) 下载