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

Java 驗證碼生成實戰:從硬編碼到 Servlet 動態繪製的四種方案演進

     編輯:Java 相關知識

驗證碼是 Web 安全的第一道防線,用於區分人機、防暴力破解、刷票、灌水。雖然單次通過率約 90%,但其必要性不容置疑。本文回顧 Java 實現驗證碼的四種方案演進,從最原始的圖片硬編碼到 Servlet 動態繪製,剖析各方案優劣與核心代碼。

方案一:圖片預製 + 硬編碼映射(反面教材)

流程:PS 預製圖片 → 前端顯示 → 後端 Map 維護「圖片檔名 ↔ 驗證碼字串」 → 提交時比對。

// 伪代码:極其低效且不安全
Map codeMap = new HashMap<>();
codeMap.put("captcha_1.jpg", "A3F9");
codeMap.put("captcha_2.jpg", "7K2M");
// ...
// 驗證時:codeMap.get(filename).equals(userInput)

致命缺陷:圖片有限、易被識別破解、維護成本極高、無法動態生成、安全性極低。僅供理解概念,嚴禁生產使用。

方案二:Servlet + BufferedImage 動態繪製(經典主流)

核心思想:「用代碼畫圖」。利用 BufferedImage 作畫布,Graphics2D 當畫筆,隨機生成字元、干擾線、噪點,最後輸出 JPEG 流。

核心流程

  1. 建立畫布:BufferedImage bi = new BufferedImage(width, height, TYPE_INT_RGB);
  2. 取得畫筆:Graphics2D g = bi.createGraphics();
  3. 繪製背景/邊框:g.fillRect(...)、g.drawRect(...)
  4. 繪製干擾線:隨機顏色、座標 g.drawLine(x1,y1,x2,y2)
  5. 繪製驗證碼字元:隨機字元、字體、顏色、旋轉角度 g.drawString(ch, x, y)
  6. 存入 Session:session.setAttribute("captcha", codeStr);
  7. 輸出圖片流:ImageIO.write(bi, "JPEG", response.getOutputStream());

關鍵代碼片段

@WebServlet("/captcha")
public class CaptchaServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        BufferedImage bi = new BufferedImage(120, 30, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = bi.createGraphics();
        
        // 背景
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, 120, 30);
        
        // 干擾線
        g.setColor(Color.GREEN);
        for (int i = 0; i < 5; i++) {
            g.drawLine(random.nextInt(120), random.nextInt(30), random.nextInt(120), random.nextInt(30));
        }
        
        // 驗證碼字元
        String chars = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ"; // 去除易混淆字元
        StringBuilder sb = new StringBuilder();
        g.setFont(new Font("微軟雅黑", Font.BOLD, 24));
        for (int i = 0; i < 4; i++) {
            char ch = chars.charAt(random.nextInt(chars.length()));
            sb.append(ch);
            g.setColor(new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256)));
            // 隨機旋轉增加識別難度
            AffineTransform orig = g.getTransform();
            g.rotate(Math.toRadians(random.nextInt(30) - 15), 20 + i * 25, 15);
            g.drawString(String.valueOf(ch), 20 + i * 25, 22);
            g.setTransform(orig);
        }
        
        // 存 Session(忽略大小寫驗證時轉大寫)
        req.getSession().setAttribute("captcha", sb.toString().toUpperCase());
        
        // 防快取 + 輸出
        resp.setHeader("Cache-Control", "no-store, no-cache");
        resp.setContentType("image/jpeg");
        ImageIO.write(bi, "JPEG", resp.getOutputStream());
        g.dispose();
    }
}

前端整合:點擊刷新防快取

<img id="captchaImg" src="/captcha" onclick="this.src='/captcha?t=' + Date.now()" />
<script>
function refreshCaptcha() {
    document.getElementById('captchaImg').src = '/captcha?t=' + Date.now();
}
</script>

關鍵點:Date.now() 或 Math.random() 作為查詢參數,強制瀏覽器繞過快取重新請求 Servlet。

方案三:Google Kaptcha / SimpleCaptcha 等成熟庫(推薦生產)

手寫 Servlet 易出 Bug(字體缺失、干擾不足、Session 同步)。成熟庫提供:

  • 中文/算術/點選/滑塊等多種驗證碼類型
  • 高度可配置(噪點、干擾線、字體、顏色、大小)
  • Spring Boot Starter 一鍵整合
<dependency>
    <groupId>com.github.penggle</groupId>
    <artifactId>kaptcha</artifactId>
    <version>2.3.2</version>
</dependency>

# application.yml
kaptcha:
  border: no
  textproducer:
    char-string: "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ"
    char-length: 4
    font-size: 28

方案四:前端生成 + 後端驗證(現代趨勢)

利用 Canvas/WebGL 在瀏覽器端生成驗證碼(如滑塊拼圖、點選文字),後端僅驗證軌跡/座標。優點:減輕伺服器渲染壓力、體驗更好;缺點:前端代碼可被逆向分析,需配合行為分析、設備指紋等風控體系。

驗證碼驗證最佳實踐

  1. 忽略大小寫:sessionCode.equalsIgnoreCase(userInput)
  2. 一次性失效:驗證成功/失敗後立即 session.removeAttribute("captcha"),防重放。
  3. 限制嘗試次數:IP/Session 級別計數,超限鎖定或要求更強驗證。
  4. HTTPS 傳輸:防中間人竊取驗證碼圖片/參數。
  5. 無障礙備選:提供語音驗證碼給視障用戶。

總結

方案適用階段優點缺點
預製圖片教學/原型零代碼繪圖極不安全、不可維護
Servlet 手繪學習/簡單項目可控、無依賴易出 Bug、功能弱、字體跨平台問題
成熟庫企業級生產功能強、穩定、易配置引入依賴、需學習配置
前端生成高併發/極致體驗零後端渲染、交互豐富前端可逆向、需風控體系配合

建議:學習階段手寫 Servlet 理解原理;生產環境直接接入 Kaptcha 或 Hutool 的 CaptchaUtil;高併發/高安全場景評估前端行為驗證方案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved