当前位置: 首页 > news >正文

用Java创建一个验证码的工具类

在Java中创建一个验证码工具类,可以通过以下代码实现。该工具类支持生成包含字母和数字的随机验证码图片,并添加干扰线和噪点以提高安全性。以下是详细实现:


完整代码实现

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Random;
import java.util.Base64;

/**
 * 验证码生成工具类
 */
public class CaptchaUtils {

    // 默认参数配置
    private static final int DEFAULT_WIDTH = 120;      // 默认图片宽度
    private static final int DEFAULT_HEIGHT = 40;      // 默认图片高度
    private static final int DEFAULT_CODE_LENGTH = 4;  // 默认验证码长度
    private static final int DEFAULT_LINE_COUNT = 5;   // 默认干扰线数量
    private static final int DEFAULT_NOISE_COUNT = 30; // 默认噪点数量

    // 可选字符集(排除易混淆字符)
    private static final String CHAR_SET = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789";

    /**
     * 生成验证码图片和对应字符串
     * @return CaptchaResult 包含验证码图片的Base64字符串和验证码值
     */
    public static CaptchaResult generateCaptcha() {
        return generateCaptcha(DEFAULT_CODE_LENGTH, DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_LINE_COUNT, DEFAULT_NOISE_COUNT);
    }

    /**
     * 自定义参数的验证码生成方法
     */
    public static CaptchaResult generateCaptcha(int codeLength, int width, int height, int lineCount, int noiseCount) {
        // 1. 生成随机验证码字符串
        String code = generateRandomCode(codeLength);

        // 2. 创建图片对象
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = image.createGraphics();

        // 3. 绘制背景色
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, width, height);

        // 4. 绘制干扰线
        drawInterferenceLines(g, width, height, lineCount);

        // 5. 绘制验证码字符
        drawCode(g, code, width, height);

        // 6. 添加噪点
        addNoise(image, width, height, noiseCount);

        // 7. 释放资源
        g.dispose();

        // 8. 转换为Base64字符串
        String base64Image = convertImageToBase64(image);

        return new CaptchaResult(code, base64Image);
    }

    // 生成随机验证码字符串
    private static String generateRandomCode(int length) {
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            int index = random.nextInt(CHAR_SET.length());
            sb.append(CHAR_SET.charAt(index));
        }
        return sb.toString();
    }

    // 绘制干扰线
    private static void drawInterferenceLines(Graphics2D g, int width, int height, int lineCount) {
        Random random = new Random();
        for (int i = 0; i < lineCount; i++) {
            int x1 = random.nextInt(width);
            int y1 = random.nextInt(height);
            int x2 = random.nextInt(width);
            int y2 = random.nextInt(height);
            g.setColor(getRandomColor());
            g.drawLine(x1, y1, x2, y2);
        }
    }

    // 绘制验证码字符
    private static void drawCode(Graphics2D g, String code, int width, int height) {
        Random random = new Random();
        g.setFont(new Font("Arial", Font.BOLD, 30));
        for (int i = 0; i < code.length(); i++) {
            // 字符颜色随机
            g.setColor(getRandomColor());
            // 字符位置偏移
            int x = (width / code.length()) * i + 10;
            int y = height - 10;
            // 添加随机旋转
            double theta = Math.toRadians(random.nextInt(30) - 15); // -15°~15°
            g.rotate(theta, x, y);
            g.drawString(String.valueOf(code.charAt(i)), x, y);
            g.rotate(-theta, x, y); // 恢复角度
        }
    }

    // 添加噪点
    private static void addNoise(BufferedImage image, int width, int height, int noiseCount) {
        Random random = new Random();
        for (int i = 0; i < noiseCount; i++) {
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            image.setRGB(x, y, getRandomColor().getRGB());
        }
    }

    // 生成随机颜色(避免浅色)
    private static Color getRandomColor() {
        Random random = new Random();
        return new Color(random.nextInt(180), random.nextInt(180), random.nextInt(180));
    }

    // 将图片转为Base64字符串
    private static String convertImageToBase64(BufferedImage image) {
        try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
            ImageIO.write(image, "JPEG", bos);
            byte[] bytes = bos.toByteArray();
            return "data:image/jpeg;base64," + Base64.getEncoder().encodeToString(bytes);
        } catch (IOException e) {
            throw new RuntimeException("生成验证码失败", e);
        }
    }

    /**
     * 验证码结果封装类
     */
    public static class CaptchaResult {
        private final String code;      // 验证码值
        private final String base64Image; // Base64格式图片

        public CaptchaResult(String code, String base64Image) {
            this.code = code;
            this.base64Image = base64Image;
        }

        public String getCode() {
            return code;
        }

        public String getBase64Image() {
            return base64Image;
        }
    }

    // 测试
    public static void main(String[] args) {
        CaptchaResult result = CaptchaUtils.generateCaptcha();
        System.out.println("验证码值: " + result.getCode());
        System.out.println("Base64图片:\n" + result.getBase64Image());
    }
}

核心功能说明

  1. 生成随机字符串

    • 使用预定义的字符集(排除易混淆字符如0/O1/I等)。
    • 通过Random生成指定位数的验证码。
  2. 创建验证码图片

    • 使用BufferedImage创建画布。
    • 设置背景色为白色,并绘制干扰线和噪点。
  3. 干扰元素设计

    • 干扰线:随机位置和颜色。
    • 噪点:随机位置的点状干扰。
    • 字符旋转:每个字符随机旋转-15°~15°。
  4. Base64编码输出

    • 将生成的图片转为Base64字符串,便于Web前端直接显示。

使用示例

// 生成默认验证码(4位,120x40像素)
CaptchaUtils.CaptchaResult result = CaptchaUtils.generateCaptcha();

// 自定义参数生成验证码(6位,200x60像素,10条干扰线,50个噪点)
CaptchaUtils.CaptchaResult customResult = CaptchaUtils.generateCaptcha(6, 200, 60, 10, 50);

// 获取验证码值和图片
String code = result.getCode();
String base64Image = result.getBase64Image();

优化点

  1. 安全性增强

    • 使用SecureRandom代替Random(需导入java.security.SecureRandom)。
    • 添加字符扭曲或缩放效果(需扩展drawCode方法)。
  2. 扩展性

    • 支持自定义字符集、字体类型、颜色范围等参数。
    • 通过Builder模式提供更灵活的配置。
  3. 性能优化

    • 缓存常用参数配置的验证码样式。
    • 使用线程安全的随机数生成器。

适用场景

  • Web应用登录/注册的验证码校验。
  • 防止机器人批量操作的接口防护。

相关文章:

  • 室内定位精度方案对比
  • win32汇编环境,对话框中使用菜单示例一
  • 《DAMA数据管理知识体系指南》第二章 数据处理伦理读书笔记总结
  • GAMES101-现代计算机图形学入门笔记
  • Hutool - DB:基于 ActiveRecord 思想的 JDBC 封装数据操作工具
  • XUnity.AutoTranslator-deepseek——调用腾讯的DeepSeek V3 API,实现Unity游戏中日文文本的自动翻译
  • Java 第八章 异常(1)
  • 详解TCP协议多种机制
  • java | MyBatis-plus映射和golang映射对比
  • 详解Nginx 配置
  • 将Neo4j用于Python学习的创新方法
  • 操作系统3.1
  • 自用题库---面试使用
  • 黑盒测试和白盒测试常用的测试方法有哪些?
  • 【科研绘图系列】R语言绘制小提琴图、散点图和韦恩图(violin scatter plot Venn)
  • C++:pthread线程分离和线程属性
  • 软件测试概念
  • 【VSCode】MicroPython环境配置
  • Java面试第六山!《MySQL基础知识点》
  • C语言基础11天:函数
  • 网站导航栏兼容性/搜索引擎优化的工具
  • 小网站开发用哪些技术/怎么做优化关键词
  • 网站怎样做移动端/网站在线客服系统 免费
  • 网站建设工作情况/搜索引擎推广实训
  • 官方网站开发商/百度营销搜索推广
  • 微信兼职网站开发/seo快速优化排名