Java图形验证码案例怎么生成

wen java案例 22

本文目录导读:

Java图形验证码案例怎么生成

  1. 基本实现方式
  2. Web应用实现(Spring Boot)
  3. 使用第三方库(Kaptcha)
  4. 前端HTML示例
  5. 验证码验证
  6. 最佳实践建议

我来详细介绍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;
}

最佳实践建议

  1. 安全性考虑

    • 验证码使用后立即清除
    • 设置验证码有效期(一般5分钟)
    • 添加防刷机制(IP限制、频率限制)
  2. 用户体验

    • 支持点击刷新验证码
    • 验证码可读性要好
    • 提供语音验证码功能(可选)
  3. 性能优化

    • 使用缓存机制
    • 避免频繁生成大尺寸图片

这样就能完整实现Java图形验证码的生成和验证功能了!

抱歉,评论功能暂时关闭!