①导包
<dependency> <groupId>com.github.axet</groupId> <artifactId>kaptcha</artifactId> <version> 0.0.9</version> </dependency>②创建配置类,用来配置验证码的生成
配置类
@Configuration public class KaptchaConfig { @Bean public DefaultKaptcha producer(){ Properties properties = new Properties(); //(选择性的设置,不是每个都需要设置) //是否需要外边框(yes,no) properties.put(“kaptcha.border”,“yes”); //边框厚度,合法值:>0 properties.put(“kaptcha.border.thickness”,“2”); //框颜色,合法值: r,g,b (and optional alpha) 或者 white,black,blue properties.put(“kaptcha.border.color”,“blue”); //字体颜色 properties.put(“kaptcha.textproducer.font.color”,“black”); //渲染效果:水纹:WaterRipple;鱼眼:FishEyeGimpy;阴影:ShadowGimpy // properties.put(“kaptcha.obscurificator.impl”,“com.google.code.kaptcha.impl.FishEyeGimpy”); //配置干扰线–噪点(只改变最后一个单词:NoNoise,DefaultNoise) properties.put(“kaptcha.noise.impl”,“com.google.code.kaptcha.impl.DefaultNoise”); //干扰 颜色,合法值: r,g,b 或者 white,black,blue. properties.put(“kaptcha.noise.color”,“yellow”); //设置图片及字体 properties.put(“kaptcha.image.width”,“90”); properties.put(“kaptcha.image.height”,“33”); properties.put(“kaptcha.textproducer.font.size”,“25”); //生成验证码的长度(也就是要几个字) properties.put(“kaptcha.textproducer.char.length”,“4”); //文字间隔 properties.put(“kaptcha.textproducer.char.space”,“5”); //和登录框背景颜色一致 //背景颜色渐变,开始颜色 properties.put(“kaptcha.background.clear.from”,“247,247,247”); //背景颜色渐变, 结束颜色 properties.put(“kaptcha.background.clear.to”,“247,247,247”); properties.put(“kaptcha.word.impl”,“com.google.code.kaptcha.text.impl.DefaultWordRenderer”); Config config = new Config(properties); DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); defaultKaptcha.setConfig(config); return defaultKaptcha; } }控制类 ③调用图片生成的类(一般为Controller层)
@Controller @RequestMapping("/producer") public class KaptchaController { @Autowired private Producer producer; @RequestMapping("/kaptcha") public void produceKaptcha(HttpServletRequest request, HttpServletResponse response) throws Exception{ response.setHeader(“Cache-Control”, “no-store, no-cache”); response.setContentType(“image/jpeg”); //生成文字验证码 String text = producer.createText(); System.out.println(text); /** *在此处做text的缓存,方便登陆校验 * 例如:HttpSession session=re.getSession(); * session.setAttribute(“code”, sb.toString()); **/ //生成图片验证码 BufferedImage image = producer.createImage(text); ServletOutputStream out = response.getOutputStream(); ImageIO.write(image,“jpg”,out); } }**
①控制层(调用处的编写) 控制层
@RequestMapping("/selfdefinitionkaptcha") public void selfDefinitionKaptcha(HttpServletResponse response) throws Exception{ Object[] objs = CreateKaptcha.createImage(); String text = (String) objs[0]; /** * 缓存验证码 *ShiroUtils.setSessionAttribute(Constants.KAPTCHA_SESSION_KEY, text); */ BufferedImage image = (BufferedImage) objs[1]; response.setHeader(“Cache-Control”, “no-store, no-cache”); response.setContentType(“image/jpeg”); ServletOutputStream out = response.getOutputStream(); ImageIO.write(image, “png”, out); }②验证码生成类
public class CreateKaptcha { // 验证码字符集 private static final char[] chars = { ‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’, ‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’, ‘G’, ‘H’, ‘I’, ‘J’, ‘K’, ‘L’, ‘M’, ‘N’, ‘O’, ‘P’, ‘Q’, ‘R’, ‘S’, ‘T’, ‘U’, ‘V’, ‘W’, ‘X’, ‘Y’, ‘Z’}; private static Map<String,String> map = new HashMap<String,String>(); private static List list= new ArrayList(); static{ map.put(“李白的女儿”,“李紫嫣”); map.put(“31*51=?”, “1581”); map.put(“潘金莲的老公”, “武大郎”); map.put(“dnf外号”, “毒奶粉”); map.put(“你是猪吗”, “是”); map.put(“光头强职业”, “伐木工”); map.put(“床前明月光”,“疑是地上霜”); map.put(“天王盖地虎”,“宝塔镇河妖”); Set set=map.keySet(); for(String s:set){ list.add(s); } set=null; } // 字符数量 private static final int SIZE = 4; // 干扰线数量 private static final int LINES = 5; // 宽度 private static final int WIDTH = 130; // 高度 private static final int HEIGHT = 35; // 字体大小 private static final int FONT_SIZE =15; /** * 生成随机验证码及图片 **/ public static Object[] createImage() { StringBuffer sb = new StringBuffer(); // 1.创建空白图片 BufferedImage image = new BufferedImage( WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB); // 2.获取图片画笔 Graphics graphic = image.getGraphics(); // 3.设置画笔颜色 graphic.setColor(Color.LIGHT_GRAY); // 4.绘制矩形背景 graphic.fillRect(0, 0, WIDTH, HEIGHT); // 5.画随机字符 Random ran = new Random(); if(ran.nextInt(2)==0){ for (int i = 0; i <SIZE; i++) { // 取随机字符索引 int n = ran.nextInt(chars.length); // 设置随机颜色 graphic.setColor(getRandomColor()); // 设置字体大小 int size=(ran.nextInt(15)+FONT_SIZE); graphic.setFont(new Font( null, Font.ITALIC,size )); // 画字符 graphic.drawString( chars[n] + “”, i * WIDTH /SIZE, HEIGHT/2+5); // 记录字符 sb.append(chars[n]); } }else{ String key = list.get(ran.nextInt(list.size())); char[] cha = key.toCharArray(); graphic.setColor(new Color(0,0,0)); for(int i=0;i<cha.length;i++){ int size = WIDTH/cha.length-2; graphic.setFont(new Font(null,Font.ITALIC+1,size)); graphic.drawString(cha[i]+"", iWIDTH/cha.length, HEIGHT/2+5); } char[] value=map.get(key).toCharArray(); for(int i=0;i<value.length;i++){ sb.append(value[i]); } } // 6.画干扰线 for (int i = 0; i < LINES; i++) { // 设置随机颜色 graphic.setColor(getRandomColor()); // 随机画线 graphic.drawLine(ran.nextInt(WIDTH), ran.nextInt(HEIGHT), ran.nextInt(WIDTH), ran.nextInt(HEIGHT)); } // 7.返回验证码和图片 return new Object[]{sb.toString(), image}; } /** * 随机取色 */ public static Color getRandomColor() { Random ran = new Random(); Color color = new Color(ran.nextInt(256), ran.nextInt(256), ran.nextInt(256)); return color; } }总结: 1.第一种更简单,第二种效果更好,更容易控制。也可以做更多花样,比如:加减乘除,唐诗宋词,都可以。 我更爱第二种。 2.两种方法对验证码的缓存采用了两种不同方法,需上心。ShiroUtils.setSessionAttribute()需要使用shiro 3、hutool工具封装的验证码使用极简,几行代码就可以实现。实际中可结合自己的条件选择