目录
-
com.github.penggle -
kaptcha -
2.3.2
CaptchaConfig
这里使用的是:1*2=2 这样的验证形式,因此我配了一个bean名为captchaProducerMath的验证码配置。
光配置不行,我通过属性properties.setProperty设置了生成格式,也就是验证码文本器。
验证码文本器通过重写getText方法定义生成的格式。格式为10以内的+-*/
注意:验证码文本器改成自己的路径
- package com.zsp.quartz.config;
-
-
- import com.google.code.kaptcha.impl.DefaultKaptcha;
- import com.google.code.kaptcha.util.Config;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
-
- import java.util.Properties;
-
- import static com.google.code.kaptcha.Constants.*;
-
- /**
- * 验证码配置
- */
- @Configuration
- public class CaptchaConfig
- {
- @Bean(name = "captchaProducer")
- public DefaultKaptcha getKaptchaBean()
- {
- DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
- Properties properties = new Properties();
- // 是否有边框 默认为true 我们可以自己设置yes,no
- properties.setProperty(KAPTCHA_BORDER, "yes");
- // 验证码文本字符颜色 默认为Color.BLACK
- properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black");
- // 验证码图片宽度 默认为200
- properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
- // 验证码图片高度 默认为50
- properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
- // 验证码文本字符大小 默认为40
- properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38");
- // KAPTCHA_SESSION_KEY
- properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode");
- // 验证码文本字符长度 默认为5
- properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
- // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
- properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
- // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
- properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
- Config config = new Config(properties);
- defaultKaptcha.setConfig(config);
- return defaultKaptcha;
- }
-
- @Bean(name = "captchaProducerMath")
- public DefaultKaptcha getKaptchaBeanMath()
- {
- DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
- Properties properties = new Properties();
- // 是否有边框 默认为true 我们可以自己设置yes,no
- properties.setProperty(KAPTCHA_BORDER, "yes");
- // 边框颜色 默认为Color.BLACK
- properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90");
- // 验证码文本字符颜色 默认为Color.BLACK
- properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");
- // 验证码图片宽度 默认为200
- properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
- // 验证码图片高度 默认为50
- properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
- // 验证码文本字符大小 默认为40
- properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35");
- // KAPTCHA_SESSION_KEY
- properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath");
- // 验证码文本生成器
- properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.zsp.quartz.config.KaptchaTextCreator");
- // 验证码文本字符间距 默认为2
- properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");
- // 验证码文本字符长度 默认为5
- properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6");
- // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
- properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
- // 验证码噪点颜色 默认为Color.BLACK
- properties.setProperty(KAPTCHA_NOISE_COLOR, "white");
- // 干扰实现类
- properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise");
- // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
- properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
- Config config = new Config(properties);
- defaultKaptcha.setConfig(config);
- return defaultKaptcha;
- }
- }
KaptchaTextCreator验证码文本生成器
继承DefaultTextCreator,覆盖原有的getText()方法
- package com.zsp.quartz.config;
-
- import com.google.code.kaptcha.text.impl.DefaultTextCreator;
-
- import java.util.Random;
-
- /**
- * 验证码文本生成器
- */
- public class KaptchaTextCreator extends DefaultTextCreator
- {
- private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(",");
-
- @Override
- public String getText()
- {
- Integer result = 0;
- Random random = new Random();
- int x = random.nextInt(10);
- int y = random.nextInt(10);
- StringBuilder suChinese = new StringBuilder();
- int randomoperands = (int) Math.round(Math.random() * 2);
- if (randomoperands == 0)
- {
- result = x * y;
- suChinese.append(CNUMBERS[x]);
- suChinese.append("*");
- suChinese.append(CNUMBERS[y]);
- }
- else if (randomoperands == 1)
- {
- if (!(x == 0) && y % x == 0)
- {
- result = y / x;
- suChinese.append(CNUMBERS[y]);
- suChinese.append("/");
- suChinese.append(CNUMBERS[x]);
- }
- else
- {
- result = x + y;
- suChinese.append(CNUMBERS[x]);
- suChinese.append("+");
- suChinese.append(CNUMBERS[y]);
- }
- }
- else if (randomoperands == 2)
- {
- if (x >= y)
- {
- result = x - y;
- suChinese.append(CNUMBERS[x]);
- suChinese.append("-");
- suChinese.append(CNUMBERS[y]);
- }
- else
- {
- result = y - x;
- suChinese.append(CNUMBERS[y]);
- suChinese.append("-");
- suChinese.append(CNUMBERS[x]);
- }
- }
- else
- {
- result = x + y;
- suChinese.append(CNUMBERS[x]);
- suChinese.append("+");
- suChinese.append(CNUMBERS[y]);
- }
- suChinese.append("=?@" + result);
- return suChinese.toString();
- }
- }
- package com.zsp.quartz.controller;
-
- import cn.hutool.core.codec.Base64;
- import com.google.code.kaptcha.Producer;
- import com.zsp.quartz.Exception.CustomException;
- import com.zsp.quartz.entity.dto.CaptchaDto;
- import com.zsp.quartz.result.Result;
- import com.zsp.quartz.service.Constants;
- import com.zsp.quartz.util.IdUtils;
- import org.springframework.data.redis.core.RedisTemplate;
- import org.springframework.data.redis.core.ValueOperations;
- import org.springframework.util.FastByteArrayOutputStream;
- import org.springframework.web.bind.annotation.*;
- import javax.annotation.Resource;
- import javax.imageio.ImageIO;
- import java.awt.image.BufferedImage;
- import java.io.IOException;
-
- @RestController
- @RequestMapping("/test")
- @CrossOrigin
- public class TestController {
- @Resource(name = "captchaProducerMath")
- private Producer captchaProducerMath;
-
- private RedisTemplate
stringRedisTemplate; -
-
- /**
- * 生成验证码
- */
- @GetMapping("/captchaImage")
- public Result
getCode() throws IOException - {
- // 保存验证码信息
- String uuid =UUID.randomUUID().toString();
- // 存入redis的key
- String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
-
- String capStr = null, code = null;
- BufferedImage image = null;
-
- // 生成验证码
- // 生成具体的验证码信息 诸如2/2=?@1
- String capText = captchaProducerMath.createText();
- // 以@进行分割获取问题
- capStr = capText.substring(0, capText.lastIndexOf("@"));
- //以@进行分割,获取最终的实际结果
- // 存入redis的值
- code = capText.substring(capText.lastIndexOf("@") + 1);
- image = captchaProducerMath.createImage(capStr);
-
- // 存入缓存 CAPTCHA_EXPIRATION验证码有效期
- stringRedisTemplate.opsForValue().set(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
- // 转换流base64信息写出
- FastByteArrayOutputStream os = new FastByteArrayOutputStream();
- try
- {
- ImageIO.write(image, "jpg", os);
- }
- catch (IOException e)
- {
- return Result.fail("生成失败",new CaptchaDto());
- }
- CaptchaDto captchaDto = new CaptchaDto();
- captchaDto.setUuid(uuid); // c8a94873-2c18-4199-871a-c6a6bd2b5241
- captchaDto.setImg(Base64.encode(os.toByteArray()));
- return Result.success("生成成功",captchaDto);
- }
-
- /**
- * 校验验证码
- * @param code 验证码
- * @param uuid 唯一标识
- * @return 结果
- */
- @PostMapping("validateCaptcha")
- public Result validateCaptcha(String code,String uuid){
- // redis的key 前端传来的
- String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
- ValueOperations
valueOperations = stringRedisTemplate.opsForValue(); - String captcha = valueOperations.get(verifyKey);
- stringRedisTemplate.delete(verifyKey);
- if (captcha == null) {
- throw new CustomException("验证码已过期");
- }
- if (!code.equalsIgnoreCase(captcha)) {
- throw new CustomException("验证码不正确");
- }
- return Result.success("验证成功");
- }
- }
-
- /**
- * 验证码 redis key
- */
- public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
postman测试生成验证码图片
base64图片要想在浏览器显示,需要前面加上 data:image/gif;base64,
逗号不要忘了
验证码校验,输入结果和uuid