本文主要是介绍kaptcha生成验证码、图片通过流的形式响应到前端,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一、简介
二、代码实现
2.1 Pom依赖
<!-- 验证码 --><dependency><groupId>com.github.penggle</groupId><artifactId>kaptcha</artifactId><version>2.3.2</version><exclusions><exclusion><artifactId>javax.servlet-api</artifactId><groupId>javax.servlet</groupId></exclusion></exclusions></dependency>
2.2 Config配置类
CaptchaConfig验证码配置
package com.lsh.user.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.*;/*** 验证码配置* @Date 2021年09月15日16:46:08* @Author LiuShihao*/
@Configuration
public class CaptchaConfig {@Bean(name = "captchaProducer")public DefaultKaptcha getKaptchaBean() {DefaultKaptcha defaultKaptcha = new DefaultKaptcha();Properties properties = new Properties();// 是否有边框 默认为true 我们可以自己设置yes,noproperties.setProperty(KAPTCHA_BORDER, "yes");// 验证码文本字符颜色 默认为Color.BLACKproperties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black");// 验证码图片宽度 默认为200properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");// 验证码图片高度 默认为50properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");// 验证码文本字符大小 默认为40properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38");// KAPTCHA_SESSION_KEYproperties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode");// 验证码文本字符长度 默认为5properties.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.ShadowGimpyproperties.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,noproperties.setProperty(KAPTCHA_BORDER, "yes");// 边框颜色 默认为Color.BLACKproperties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90");// 验证码文本字符颜色 默认为Color.BLACKproperties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");// 验证码图片宽度 默认为200properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");// 验证码图片高度 默认为50properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");// 验证码文本字符大小 默认为40properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35");// KAPTCHA_SESSION_KEYproperties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath");// 验证码文本生成器properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.lsh.user.config.KaptchaTextCreator");// 验证码文本字符间距 默认为2properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");// 验证码文本字符长度 默认为5properties.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.BLACKproperties.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.ShadowGimpyproperties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");Config config = new Config(properties);defaultKaptcha.setConfig(config);return defaultKaptcha;}
}
KaptchaTextCreator验证码文本生成器
package com.lsh.user.config;import com.google.code.kaptcha.text.impl.DefaultTextCreator;import java.util.Random;/*** 验证码文本生成器* @Date 2021年09月15日16:46:08* @Author LiuShihao*/
public class KaptchaTextCreator extends DefaultTextCreator {private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(",");@Overridepublic 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();}
}
2.3 CaptchaController控制层
此处生成验证码Code、UUID、并存入Redis中
在登录时进行验证UUID和Code与Redis中的是否一致。
package com.lsh.user.controller;import com.google.code.kaptcha.Producer;
import com.lsh.common.constant.Constants;
import com.lsh.common.redis.RedisCache;
import com.lsh.common.util.AjaxResult;
import com.lsh.common.util.Base64;
import com.lsh.common.util.uuid.IdUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Map;
import java.util.concurrent.TimeUnit;/*** 验证码操作处理* @Date 2021年09月15日16:46:08* @Author LiuShihao*/
@RestController
public class CaptchaController {@Resource(name = "captchaProducer")private Producer captchaProducer;@Resource(name = "captchaProducerMath")private Producer captchaProducerMath;@Autowiredprivate RedisCache redisCache;@AutowiredStringRedisTemplate stringRedisTemplate;// 验证码类型@Value("${captcha.type}")private String captchaType;/*** 生成验证码* @param response* @return UUID 本次图片验证码唯一标识* @return img 图片验证码Base64编码* @throws IOException*/@GetMapping("/captchaImage")public AjaxResult getCode(HttpServletResponse response) throws IOException {// 保存验证码信息String uuid = IdUtils.simpleUUID();String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;String capStr = null, code = null;BufferedImage image = null;// 生成验证码if ("math".equals(captchaType)) {String capText = captchaProducerMath.createText();capStr = capText.substring(0, capText.lastIndexOf("@"));code = capText.substring(capText.lastIndexOf("@") + 1);image = captchaProducerMath.createImage(capStr);}else if ("char".equals(captchaType)) {capStr = code = captchaProducer.createText();image = captchaProducer.createImage(capStr);}System.out.println("code:"+code+" , uuid:"+uuid);
// stringRedisTemplate.opsForValue().set(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);// 转换流信息写出FastByteArrayOutputStream os = new FastByteArrayOutputStream();try {ImageIO.write(image, "jpg", os);}catch (IOException e) {return AjaxResult.error(e.getMessage());}System.out.println("img:"+Base64.encode(os.toByteArray()));AjaxResult ajax = AjaxResult.success();ajax.put("uuid", uuid);ajax.put("img", Base64.encode(os.toByteArray()));return ajax;}
直接返回验证码图片至浏览器
主要就是通过FileInputStream和响应的输出流,并设置响应的请求头:
/*** 直接将图片的文件流响应到前端* @param request* @param response* @throws Exception*/@GetMapping("/getCaptchaImage")public void getCaptchaImage(HttpServletRequest request, HttpServletResponse response) throws Exception {File file = new File("./img.jpg");FileInputStream fis = new FileInputStream(file);ServletOutputStream os = response.getOutputStream();response.addHeader("Content-Length", "" + file.length());response.setContentType("image/jpg");byte[] bytes = new byte[1024];while (fis.read(bytes) != -1){os.write(bytes);}fis.close();os.close();System.out.println("===完成===");}
2.4 yml配置
captcha:# 验证码类型 math 数组计算 char 字符验证type: char
三、测试
并且两分钟后失效
四、源码
其中的工具类就不在贴出来了,代码已上传仓库。
https://gitee.com/L1692312138/spring-cloud-alibaba
这篇关于kaptcha生成验证码、图片通过流的形式响应到前端的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!