首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 圖形驗證碼 生成與驗證完整實作

     編輯:Java 相關知識

核心需求

防止機器人自動提交表單,需生成含干擾線、噪點、扭曲字符的圖片驗證碼,並能在伺服器端驗證使用者輸入。

完整實作類別


import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.imageio.ImageIO;
import java.io.OutputStream;

public class CaptchaUtil {
    private static final String CHARS = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
    private static final int WIDTH = 120, HEIGHT = 40;
    private static final int CODE_LENGTH = 4;
    private static final int LINE_COUNT = 5;
    private static final Random RANDOM = new Random();

    // 生成驗證碼圖片並輸出到 OutputStream (如 HttpServletResponse.getOutputStream())
    public static String generate(OutputStream out) throws Exception {
        BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = image.createGraphics();

        // 1. 背景
        g.setColor(getRandomColor(200, 250));
        g.fillRect(0, 0, WIDTH, HEIGHT);

        // 2. 干擾線
        for (int i = 0; i < LINE_COUNT; i++) {
            g.setColor(getRandomColor(100, 200));
            int x1 = RANDOM.nextInt(WIDTH);
            int y1 = RANDOM.nextInt(HEIGHT);
            int x2 = RANDOM.nextInt(WIDTH);
            int y2 = RANDOM.nextInt(HEIGHT);
            g.drawLine(x1, y1, x2, y2);
        }

        // 3. 噪點
        for (int i = 0; i < 50; i++) {
            g.setColor(getRandomColor(100, 200));
            int x = RANDOM.nextInt(WIDTH);
            int y = RANDOM.nextInt(HEIGHT);
            g.drawOval(x, y, 1, 1);
        }

        // 4. 驗證碼字符
        StringBuilder code = new StringBuilder();
        Font font = new Font("Consolas", Font.BOLD, 28);
        g.setFont(font);
        for (int i = 0; i < CODE_LENGTH; i++) {
            char c = CHARS.charAt(RANDOM.nextInt(CHARS.length()));
            code.append(c);
            g.setColor(getRandomColor(20, 100));
            // 隨機旋轉角度
            AffineTransform orig = g.getTransform();
            g.rotate(RANDOM.nextDouble() * 0.4 - 0.2, 20 * i + 15, 25);
            g.drawString(String.valueOf(c), 20 * i + 10, 30);
            g.setTransform(orig);
        }

        g.dispose();
        ImageIO.write(image, "PNG", out);
        return code.toString();
    }

    private static Color getRandomColor(int min, int max) {
        int r = min + RANDOM.nextInt(max - min);
        int g = min + RANDOM.nextInt(max - min);
        int b = min + RANDOM.nextInt(max - min);
        return new Color(r, g, b);
    }
}

Servlet 整合範例


@WebServlet("/captcha")
public class CaptchaServlet extends HttpServlet {
    @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        resp.setContentType("image/png");
        resp.setHeader("Pragma", "no-cache");
        resp.setHeader("Cache-Control", "no-cache");
        resp.setDateHeader("Expires", 0);

        try (OutputStream out = resp.getOutputStream()) {
            String code = CaptchaUtil.generate(out);
            req.getSession().setAttribute("captcha_code", code); // 存入 Session
        }
    }
}

前端驗證流程


// HTML



// JS 驗證 (提交前)
$('#form').submit(function() {
    var input = $('#captchaInput').val().toUpperCase();
    // 通常送往後端驗證,這裡僅示範前端邏輯
    $.post('/verify', {captcha: input}, function(res) {
        if (!res.valid) { alert('驗證碼錯誤'); return false; }
    });
});

後端驗證


@PostMapping("/verify")
public Map<String, Boolean> verify(@RequestParam String captcha, HttpSession session) {
    String expected = (String) session.getAttribute("captcha_code");
    boolean valid = expected != null && expected.equalsIgnoreCase(captcha);
    if (valid) session.removeAttribute("captcha_code"); // 一次性使用
    return Map.of("valid", valid);
}

進階強化方向

  • 字體多樣化:載入多種 TTF 字體隨機選擇。
  • 曲線扭曲:使用 Graphics2D.draw(Shape) 繪製貝茲曲線路徑。
  • 點擊/滑塊驗證:前端交互式驗證(如 Geetest、滑塊拼圖),體驗更好。
  • 分散式 Session:集群環境下驗證碼存入 Redis,設定 TTL 60-120 秒。

安全性提醒

  1. 驗證碼必須在伺服器端驗證,前端 JS 僅作輔助。
  2. 限制嘗試次數(如 5 次失效),防暴力破解。
  3. HTTPS 傳輸,防止中間人攔截圖片內容。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved