Spring项目中使用GoogleKaptcha 生成验证码
前言:google captcha 是google生成验证码的一个工具类,其原理是将随机生成字符串保存到session中,同时以图片的形式返回给页面,之后前台页面提交到后台进行对比。
0.前提:在tomcat的bin目录下的catlina.sh文件中加入以下配置
export JAVA_OPTS="-Djava.awt.headless=true"
1、jar包准备
<dependency> <groupId>com.github.penggle</groupId> <artifactId>kaptcha</artifactId> <version>2.3.2</version> </dependency>
2、spring bean的配置
1<!-- Kaptcha验证码生成器 -->
<bean name="producer" class="com.google.code.kaptcha.impl.DefaultKaptcha" scope="singleton">
<property name="config">
<bean class="com.google.code.kaptcha.util.Config">
<constructor-arg>
<props>
<prop key="kaptcha.border">no</prop>
<prop key="kaptcha.textproducer.font.color">black</prop>
<prop key="kaptcha.textproducer.char.space">5</prop>
<prop key="kaptcha.textproducer.font.names">STIX</prop>
</props>
</constructor-arg>
</bean>
</property>
</bean>
注意:kaptcha.textproducer.font.names的配置。必须选择linux或者Windows存在的字体。
以下是在线上环境由于配置了服务器不存在字体导致的的问题:
1.会导致加载bean失败导致应用启动失败。报错
java.lang.ArrayIndexOutOfBoundsException: 0
at sun.font.CompositeFont.getSlotFont(CompositeFont.java:351)
at sun.font.CompositeGlyphMapper.initMapper(CompositeGlyphMapper.java:81)
at sun.font.CompositeGlyphMapper.<init>(CompositeGlyphMapper.java:62)
at sun.font.CompositeFont.getMapper(CompositeFont.java:409)
at sun.font.GlyphList.mapChars(GlyphList.java:269)
at sun.font.GlyphList.setFromChars(GlyphList.java:262)
at sun.java2d.pipe.GlyphListPipe.drawChars(GlyphListPipe.java:103)
at sun.java2d.SunGraphics2D.drawChars(SunGraphics2D.java:3036)
2.或者是应用启动但是图片没内容如下图所示
3、Controller的两个方法
1 package com.ccg.controller; 2 3 import java.awt.image.BufferedImage; 4 import java.io.IOException; 5 import java.io.PrintWriter; 6 7 import javax.annotation.Resource; 8 import javax.imageio.ImageIO; 9 import javax.servlet.ServletOutputStream; 10 import javax.servlet.http.HttpServletRequest; 11 import javax.servlet.http.HttpServletResponse; 12 import javax.servlet.http.HttpSession; 13 14 import org.springframework.stereotype.Controller; 15 import org.springframework.web.bind.annotation.RequestMapping; 16 import org.springframework.web.bind.annotation.RequestParam; 17 import org.springframework.web.servlet.ModelAndView; 18 19 import com.google.code.kaptcha.Constants; 20 import com.google.code.kaptcha.Producer; 21 22 @Controller 23 @RequestMapping("captcha") 24 public class CaptchaController { 25 26 @Resource 27 private Producer captchaProducer; 28 38 @RequestMapping("getCaptchaCode") 39 public ModelAndView getCaptchaCode(HttpServletRequest request, HttpServletResponse response) throws IOException{ 40 HttpSession session = request.getSession(); 41 42 response.setDateHeader("Expires", 0); 43 response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate"); 44 response.addHeader("Cache-Control", "post-check=0, pre-check=0"); 45 response.setHeader("Pragma", "no-cache"); 46 response.setContentType("image/jpeg"); 47 48 //生成验证码文本 49 String capText = captchaProducer.createText(); 50 session.setAttribute(Constants.KAPTCHA_SESSION_KEY, capText); 51 System.out.println("生成验证码文本===="+capText); 52 //利用生成的字符串构建图片 53 BufferedImage bi = captchaProducer.createImage(capText); 54 ServletOutputStream out = response.getOutputStream(); 55 ImageIO.write(bi, "jpg", out); 56 57 try { 58 out.flush(); 59 } finally { 60 out.close(); 61 } 62 return null; 63 } 64 65 74 @RequestMapping("checkCaptchaCode") 75 public void checkCaptchaCode(HttpServletRequest request, HttpServletResponse response,@RequestParam("captchaCode") String captchaCode){ 76 System.out.println("页面输入验证码===="+captchaCode); 77 78 response.setCharacterEncoding("UTF-8"); 79 response.setHeader("Pragma", "No-cache"); 80 response.setHeader("Cache-Control", "no-cache"); 81 response.setDateHeader("Expires", 0); 82 83 String generateCode =(String) request.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY); 84 String result = ""; 85 if(generateCode.equals(captchaCode)){ 86 result = "验证成功"; 87 }else{ 88 result = "输入错误"; 89 } 90 PrintWriter out = null; 91 try { 92 out = response.getWriter(); 93 } catch (IOException e) { 94 e.printStackTrace(); 95 } 96 out.print(result); 97 out.flush(); 98 } 99 }