java实现验证码
kaptcha
原文链接:https://blog.csdn.net/qq_43842093/article/details/130675098
1. 导入依赖
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
</dependency>
2. 编写配置类
package simulationvirtual.VirtualExperiment.config;
import com.google.code.kaptcha.Producer;
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;
@Configuration
public class KaptchaConfig {
/**
* Kaptcha图形验证码工具配置类
* @author: Xiongch
* @param:
* @return: com.google.code.kaptcha.Producer
* @date: 2022/9/9 15:47
*/
@Bean
public Producer kaptchaProducer() {
// 实例一个DefaultKaptcha
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
// 创建配置对象
Properties properties = new Properties();
// 设置边框
properties.setProperty("kaptcha.border", "yes");
// 设置颜色
properties.setProperty("kaptcha.border.color", "105,179,90");
// 设置字体颜色
properties.setProperty("kaptcha.textproducer.font.color", "blue");
// 设置宽度
properties.setProperty("kaptcha.image.width", "125");
// 高度
properties.setProperty("kaptcha.image.height", "50");
// 设置session.key
properties.setProperty("kaptcha.session.key", "code");
// 设置文本长度
properties.setProperty("kaptcha.textproducer.char.length", "4");
// 设置字体
properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑");
// 将以上属性设置为实例一个DefaultKaptcha的属性
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
// 将defaultKaptcha返回
return defaultKaptcha;
}
}
2.1 详细配置
序号 | 属性名 | 描述 | 示例 |
---|---|---|---|
1 | kaptcha.width | 验证码宽度 | 200 |
2 | kaptcha.height | 验证码高度 | 50 |
3 | kaptcha.border.enabled | 是否显示边框 | false |
4 | kaptcha.border.color | 边框颜色 | black |
5 | kaptcha.border.thickness | 边框厚度 | 2 |
6 | kaptcha.content.length | 验证码文本长度 | 5 |
7 | kaptcha.content.source | 文本源 | abcde2345678gfynmnpwx |
8 | kaptcha.content.space | 文本间隔 | 2 |
9 | kaptcha.font.name | 字体名称 | Arial |
10 | kaptcha.font.size | 字体大小 | 40 |
11 | kaptcha.font.color | 字体颜色 | black |
12 | kaptcha.background-color.from | 背景颜色(开始渐变色) | lightGray |
13 | kaptcha.background-color.to | 背景颜色(结束渐变色) | white |
3. controller接口
package simulationvirtual.VirtualExperiment.controller.tools;
import com.google.code.kaptcha.Producer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import simulationvirtual.VirtualExperiment.util.AjaxResult;
import simulationvirtual.VirtualExperiment.util.Base64;
import simulationvirtual.VirtualExperiment.util.UUIDutil;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
@RestController
public class KaptchaController {
@Autowired
private RedisTemplate<String,Object> redisTemplate;
@Autowired
private Producer kaptchaProduer;
/**
* 生成图形验证码
* @author: Xiongch
* @param:null
* @return:Ajax_Result(统一返回工具)
* @date: 2022/9/9 15:47
*/
@GetMapping("/kaptcha")
public AjaxResult getKaptcha(HttpServletResponse response, HttpSession session){
AjaxResult Ajax_Result = AjaxResult.success();
String imagecode = kaptchaProduer.createText();
// 生成图片
BufferedImage image = kaptchaProduer.createImage(imagecode);
// 将验证码存入Session
session.setAttribute("kaptcha",imagecode);
//将图片输出给浏览器
String uuid = UUIDutil.getUUID();//uuid-->验证码唯一标识
FastByteArrayOutputStream os = new FastByteArrayOutputStream();
try {
response.setContentType("image/png");
ImageIO.write(image,"png",os);
//验证码实现redis缓存,过期时间2分钟
session.setAttribute("uuid",imagecode);
redisTemplate.opsForValue().set(uuid,imagecode,2, TimeUnit.MINUTES);
} catch (IOException e) {
return AjaxResult.error(e.getMessage());
}
Ajax_Result.put("uuid",uuid);
Ajax_Result.put("img", Base64.encode(os.toByteArray()));
return Ajax_Result;
}
}
java 画验证码
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.*;
import java.util.concurrent.TimeUnit;
public class CaptchaUtil1 {
// 验证码图片宽度
private static final int WIDTH = 120;
// 验证码图片高度
private static final int HEIGHT = 60;
// 随机字符数组
private static final char[] CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".toCharArray();
// 创建一个 Caffeine 缓存对象,设置缓存大小和过期时间
private static Cache<String, String> captchaCache = Caffeine.newBuilder()
.maximumSize(10000) // 设置最大缓存条目数
.expireAfterWrite(3, TimeUnit.MINUTES) // 设置写入后过期时间
.build();
public static String convertImageToBase64(BufferedImage image) {
try {
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(image, "png", os);
return "data:image/png;base64," + Base64.getEncoder().encodeToString(os.toByteArray());
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public static Map getBase64Image(){
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
// 创建 BufferedImage 对象
BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
// 获取 Graphics2D 对象
Graphics2D g2d = image.createGraphics();
// 设置绘制参数
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, WIDTH, HEIGHT);
g2d.setColor(Color.BLACK);
// 设置字体大小
g2d.setFont(new Font(null, Font.PLAIN, 20));
// 生成随机字符串
String captchaText = generateRandomString(4);
// 在 BufferedImage 上绘制文本
// 随机位置绘制四个字符,并且设置倾斜
for (int i = 0; i < 4; i++) {
// 获取当前字符
char c = captchaText.charAt(i);
int angle = -10;
// 设置字体倾斜
AffineTransform fontAT = new AffineTransform();
fontAT.rotate(Math.toRadians(angle), (i + 1) * WIDTH / 5.0, HEIGHT / 2.0); // 将字体倾斜 angle 度
Font font = g2d.getFont().deriveFont(fontAT);
g2d.setFont(font);
// 绘制字符
g2d.drawString(String.valueOf(c), (i + 1) * WIDTH / 5, HEIGHT / 2);
// 调整下一个字符的倾斜角度
angle += 5 + (int) (Math.random() * 10); // 角度增加 5 到 15 度之间的随机值
}
// 绘制干扰线
for (int i = 0; i < 10; i++) {
g2d.setColor(getRandomColor(100, 200));
int x1 = (int) (Math.random() * WIDTH);
int y1 = (int) (Math.random() * HEIGHT);
int x2 = (int) (Math.random() * WIDTH);
int y2 = (int) (Math.random() * HEIGHT);
g2d.drawLine(x1, y1, x2, y2);
}
// 释放资源
g2d.dispose();
String base64 = convertImageToBase64(image);
HashMap<String, String> map = new HashMap<>();
map.put("uuid", uuid);
map.put("image", base64);
map.put("text", captchaText);
captchaCache.put(uuid, captchaText);
return map;
}
// 获取随机颜色
private static Color getRandomColor(int min, int max) {
int r = min + (int) (Math.random() * (max - min));
int g = min + (int) (Math.random() * (max - min));
int b = min + (int) (Math.random() * (max - min));
return new Color(r, g, b);
}
public static boolean validateCaptcha(String uuid, String text) {
String answer = captchaCache.getIfPresent(uuid);
if (answer == null) {
return false;
}
answer.toLowerCase();
text.toLowerCase();
boolean result = text.equals(answer);
if (result) {
captchaCache.invalidate(uuid);
}
return result;
}
// 生成随机字符串
private static String generateRandomString(int length) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++) {
sb.append(CHARACTERS[(int)(Math.random() * CHARACTERS.length)]);
}
return sb.toString();
}
}
评论区