本文目录导读:

我来详细介绍Java生成图形验证码的几种常见实现方法:
基本实现方式
使用Java AWT/Swing生成
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;
public class CaptchaGenerator {
// 生成验证码
public static BufferedImage generateCaptcha(String code) {
int width = 120;
int height = 40;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = image.createGraphics();
// 设置背景色
g.setColor(Color.WHITE);
g.fillRect(0, 0, width, height);
// 设置字体
g.setFont(new Font("Arial", Font.BOLD, 24));
// 绘制验证码
Random random = new Random();
for (int i = 0; i < code.length(); i++) {
// 随机颜色
g.setColor(new Color(random.nextInt(255),
random.nextInt(255),
random.nextInt(255)));
// 随机旋转角度
double angle = random.nextInt(30) - 15;
g.rotate(Math.toRadians(angle), 20 + i * 25, 25);
g.drawString(String.valueOf(code.charAt(i)), 10 + i * 25, 30);
g.rotate(-Math.toRadians(angle), 20 + i * 25, 25);
}
// 添加干扰线
for (int i = 0; i < 5; i++) {
g.setColor(new Color(random.nextInt(255),
random.nextInt(255),
random.nextInt(255)));
g.drawLine(random.nextInt(width), random.nextInt(height),
random.nextInt(width), random.nextInt(height));
}
g.dispose();
return image;
}
// 生成随机验证码字符串
public static String generateCode(int length) {
String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
StringBuilder code = new StringBuilder();
Random random = new Random();
for (int i = 0; i < length; i++) {
code.append(chars.charAt(random.nextInt(chars.length())));
}
return code.toString();
}
public static void main(String[] args) throws IOException {
String code = generateCode(4);
System.out.println("验证码: " + code);
BufferedImage image = generateCaptcha(code);
ImageIO.write(image, "jpg", new File("captcha.jpg"));
}
}
Web应用实现(Spring Boot)
添加Maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
验证码Controller
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
@RestController
public class CaptchaController {
@GetMapping("/captcha")
public void getCaptcha(HttpServletResponse response, HttpSession session) throws IOException {
// 设置响应类型
response.setContentType("image/jpeg");
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
// 生成验证码
int width = 120;
int height = 40;
String code = generateCode(4);
// 存储验证码到session
session.setAttribute("captcha", code);
// 生成图片
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = image.createGraphics();
// 设置背景
g.setColor(Color.WHITE);
g.fillRect(0, 0, width, height);
// 设置字体
g.setFont(new Font("Arial", Font.BOLD, 24));
// 绘制验证码
Random random = new Random();
for (int i = 0; i < code.length(); i++) {
g.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
g.drawString(String.valueOf(code.charAt(i)), 10 + i * 25, 30);
}
// 添加干扰线
for (int i = 0; i < 5; i++) {
g.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
g.drawLine(random.nextInt(width), random.nextInt(height),
random.nextInt(width), random.nextInt(height));
}
g.dispose();
// 输出到response
ImageIO.write(image, "JPEG", response.getOutputStream());
response.getOutputStream().close();
}
private String generateCode(int length) {
String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
StringBuilder code = new StringBuilder();
Random random = new Random();
for (int i = 0; i < length; i++) {
code.append(chars.charAt(random.nextInt(chars.length())));
}
return code.toString();
}
}
使用第三方库(Kaptcha)
添加依赖
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
</dependency>
Kaptcha配置
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 {
@Bean
public DefaultKaptcha getDefaultKaptcha() {
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", "110");
properties.setProperty("kaptcha.image.height", "40");
// 字体大小
properties.setProperty("kaptcha.textproducer.font.size", "30");
// session key
properties.setProperty("kaptcha.session.key", "code");
// 验证码长度
properties.setProperty("kaptcha.textproducer.char.length", "4");
// 字体
properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑");
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}
使用Kaptcha的Controller
import com.google.code.kaptcha.impl.DefaultKaptcha;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.IOException;
@RestController
public class KaptchaController {
@Autowired
private DefaultKaptcha captchaProducer;
@GetMapping("/kaptcha")
public void getKaptcha(HttpServletResponse response, HttpSession session) throws IOException {
response.setDateHeader("Expires", 0);
response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
response.addHeader("Cache-Control", "post-check=0, pre-check=0");
response.setHeader("Pragma", "no-cache");
response.setContentType("image/jpeg");
// 生成验证码文本
String capText = captchaProducer.createText();
// 存储到session
session.setAttribute("captcha", capText);
// 生成验证码图片
BufferedImage bi = captchaProducer.createImage(capText);
// 输出图片
ImageIO.write(bi, "jpg", response.getOutputStream());
response.getOutputStream().close();
}
}
前端HTML示例
<!DOCTYPE html>
<html>
<head>验证码示例</title>
<script>
function refreshCaptcha() {
document.getElementById('captchaImg').src =
'/captcha?' + new Date().getTime();
}
function submitForm() {
const code = document.getElementById('code').value;
fetch('/verify-captcha?code=' + code)
.then(response => response.json())
.then(data => {
if (data.valid) {
alert('验证码正确!');
} else {
alert('验证码错误!');
refreshCaptcha();
}
});
}
</script>
</head>
<body>
<h2>验证码测试</h2>
<div>
<img id="captchaImg" src="/captcha" alt="验证码" onclick="refreshCaptcha()">
<button onclick="refreshCaptcha()">刷新</button>
</div>
<div>
<input type="text" id="code" placeholder="请输入验证码">
<button onclick="submitForm()">提交</button>
</div>
</body>
</html>
验证码验证
@GetMapping("/verify-captcha")
public Map<String, Object> verifyCaptcha(String code, HttpSession session) {
Map<String, Object> result = new HashMap<>();
String captchaCode = (String) session.getAttribute("captcha");
if (captchaCode != null && captchaCode.equalsIgnoreCase(code)) {
result.put("valid", true);
// 验证成功后清除session中的验证码
session.removeAttribute("captcha");
} else {
result.put("valid", false);
}
return result;
}
最佳实践建议
-
安全性考虑:
- 验证码使用后立即清除
- 设置验证码有效期(一般5分钟)
- 添加防刷机制(IP限制、频率限制)
-
用户体验:
- 支持点击刷新验证码
- 验证码可读性要好
- 提供语音验证码功能(可选)
-
性能优化:
- 使用缓存机制
- 避免频繁生成大尺寸图片
这样就能完整实现Java图形验证码的生成和验证功能了!