java图片验证码,不用引任何包,自己就能搞定
2023-02-03 本文已影响0人
不知不怪
1 在使用这个验证码依赖时发现里面竟然引用了servlet,springboot3大量类调整导致这个工具不能用了,
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
</dependency>
1675486770818.png
想了一下自写个图片验证码,完全没有必要引一个依赖
2 验证码工具类
package com.gzz.config;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
public class Kaptcha {
private static final Random RAND = new Random();
private static final int LENGTH = 4;// 验证码位数
private static final int SIZE = 60;// 字号
private static final int WIDTH = 160;// 画板宽
private static final int HEIGHT = 60;// 画板高
private static final BufferedImage IMG = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_BGR);// 创建画板
private static final Graphics2D GRAPH = IMG.createGraphics();// 画笔
public static byte[] imageByte(String code) throws IOException {
GRAPH.setColor(color());// 随机颜色
GRAPH.fillRect(0, 0, WIDTH, HEIGHT); // 0,0,100宽度,30表示高度
GRAPH.setColor(color());// 随机颜色
GRAPH.setFont(font());// 随机字体-可选
GRAPH.drawString(code, 10, 50);// 坐标10,50开始画
GRAPH.setStroke(new BasicStroke(2f));// 画笔
for (int i = 0; i < 6; i++) {// 干扰线-可选
GRAPH.setColor(color());
GRAPH.drawLine(RAND.nextInt(WIDTH), RAND.nextInt(HEIGHT), RAND.nextInt(WIDTH), RAND.nextInt(HEIGHT));// 区域内随机两个点画线
}
for (int i = 0; i < 20; i++) {// 干扰点-可选
GRAPH.setColor(color());
GRAPH.drawOval(RAND.nextInt(WIDTH), RAND.nextInt(HEIGHT), 2, 2);
}
ByteArrayOutputStream stream = new ByteArrayOutputStream(); // 转成字节数组
ImageIO.write(IMG, "jpg", stream);
// ImageIO.write(image, "jpg", new File("d:/code.jpg"));
return stream.toByteArray();
}
// 纯随机字符
public static String code() {
StringBuilder code = new StringBuilder();
for (int i = 0; i < LENGTH; i++) {
switch (RAND.nextInt(3)) {
case 0 -> code.append((char) (RAND.nextInt(26) + 65));
case 1 -> code.append((char) (RAND.nextInt(26) + 97));
case 2 -> code.append(RAND.nextInt(10));
}
}
return code.toString();
}
// 随机字体
private static Font font() {
Font[] fonts = { new Font("微软雅黑", Font.ITALIC, SIZE), //
new Font("新宋体", Font.PLAIN, SIZE), //
new Font("Microsoft YaHei Ul", Font.PLAIN, SIZE), //
new Font("仿宋", Font.PLAIN, SIZE), //
new Font("Cambria", Font.BOLD, SIZE) };
return fonts[RAND.nextInt(fonts.length)];
}
// 随机颜色
private static Color color() {
return new Color(RAND.nextInt(256), RAND.nextInt(256), RAND.nextInt(256));
}
private static String word() {
String words = "acdefghjkmnprstwxy34578ACEFGHJKLMNPQRSTWXY";
return String.valueOf(words.charAt(RAND.nextInt(words.length())));
}
// 实现不同字符的不同颜色
private void randomColor() {
StringBuilder code = new StringBuilder();
for (int i = 0, left = 10; i < 4; i++, left += 20) {
GRAPH.setColor(color());
GRAPH.setFont(font());
String word = word();
code.append(word);
GRAPH.drawString(word, left, 25);
}
}
// 实现不同字符的不同旋转角度
private void rotate() {
StringBuilder code = new StringBuilder();// 接收验证码的字符串
for (int i = 0, left = 10, x = 15; i < 4; i++, left += 20, x += 20) {
GRAPH.setColor(color());// 随机颜色
GRAPH.setFont(font());// 随机字体
String word = word();// 获取随机字符
code.append(word);// 拼接到字符串string
double th = RAND.nextInt(100) / 100.0;// 随机旋转角度
GRAPH.rotate(th, x, 25);// 旋转一个字符
GRAPH.drawString(word, left, 25);// 画字符串
GRAPH.rotate(-th, x, 25);// 调回原始角度
}
}
}
3 Controller 调用
package com.gzz.controller;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.gzz.config.Kaptcha;
/**
* @author https://www.jianshu.com/u/3bd57d5f1074
* @date 2023-02-04 14:50:00
*/
@RestController
public class HelloController {
Logger log = LoggerFactory.getLogger(HelloController.class);
@RequestMapping({ "/", "index" })
public ResponseEntity<byte[]> downCode() throws IOException {
String code = Kaptcha.code(); // 放到缓存里
log.info("code={}", code);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_JPEG);
return new ResponseEntity<>(Kaptcha.imageByte(code), headers, HttpStatus.OK);
}
}