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

基於 Patchca 實現生產級圖形驗證碼:配置、干擾線與 Session 管理

     編輯:Java 相關知識

技術選型:為什麼選 Patchca?

  • 輕量級、零依賴(僅需 patchca.jar)
  • 支援多種干擾效果:曲線、大理石、雙波紋、抖動、擴散
  • 可自定義字符集、顏色、字體、尺寸
  • 線程安全,適合高併發場景

Maven 依賴

<dependency>
    <groupId>com.github.bingoohuang</groupId>
    <artifactId>patchca</artifactId>
    <version>0.0.1</version> 
</dependency>

驗證碼 Servlet 完整實現

@WebServlet("/captcha.jpg")
public class CaptchaServlet extends HttpServlet {

    private static final ConfigurableCaptchaService CAPTCHA_SERVICE = new ConfigurableCaptchaService();
    private static final Random RANDOM = new Random();

    static {
        // 1. 自定義顏色工廠:隨機生成深色字符
        CAPTCHA_SERVICE.setColorFactory(new ColorFactory() {
            @Override public Color getColor(int x) {
                int[] rgb = new int[3];
                int darkIdx = RANDOM.nextInt(3);
                for (int i = 0; i < 3; i++) {
                    rgb[i] = (i == darkIdx) ? RANDOM.nextInt(71) : RANDOM.nextInt(256);
                }
                return new Color(rgb[0], rgb[1], rgb[2]);
            }
        });

        // 2. 字符工廠:排除易混淆字符 (0/O, 1/I/l 等)
        RandomWordFactory wordFactory = new RandomWordFactory();
        wordFactory.setCharacters("23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz");
        wordFactory.setMinLength(4);
        wordFactory.setMaxLength(4);
        CAPTCHA_SERVICE.setWordFactory(wordFactory);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        // 隨機選擇干擾效果
        switch (RANDOM.nextInt(5)) {
            case 0: CAPTCHA_SERVICE.setFilterFactory(new CurvesRippleFilterFactory(CAPTCHA_SERVICE.getColorFactory())); break;
            case 1: CAPTCHA_SERVICE.setFilterFactory(new MarbleRippleFilterFactory()); break;
            case 2: CAPTCHA_SERVICE.setFilterFactory(new DoubleRippleFilterFactory()); break;
            case 3: CAPTCHA_SERVICE.setFilterFactory(new WobbleRippleFilterFactory()); break;
            case 4: CAPTCHA_SERVICE.setFilterFactory(new DiffuseRippleFilterFactory()); break;
        }

        // 禁止緩存
        resp.setHeader("Pragma", "No-cache");
        resp.setHeader("Cache-Control", "no-cache");
        resp.setDateHeader("Expires", 0);
        resp.setContentType("image/png");

        // 生成驗證碼並寫入輸出流
        String token = EncoderHelper.getChallangeAndWriteImage(CAPTCHA_SERVICE, "png", resp.getOutputStream());

        // 存入 Session
        HttpSession session = req.getSession(true);
        session.setAttribute("captcha_token", token.toLowerCase()); // 統一小寫比對
    }
}

前端整合與驗證

HTML 模板

<img id="captchaImg" src="/captcha.jpg" onclick="this.src='/captcha.jpg?t='+Date.now()" style="cursor:pointer">
<input type="text" name="captcha" placeholder="輸入驗證碼">

後端驗證(Controller/Filter)

@PostMapping("/login")
public Result login(@RequestParam String username, @RequestParam String password,
                    @RequestParam String captcha, HttpSession session) {
    String expected = (String) session.getAttribute("captcha_token");
    if (expected == null || !expected.equals(captcha.toLowerCase())) {
        return Result.error("驗證碼錯誤或已過期");
    }
    session.removeAttribute("captcha_token"); // 一次性使用
    // 後續業務邏輯...
    return Result.success();
}

進階客製化

需求實現方式
自定義字體/字號wordFactory.setFont(new Font("Arial", Font.BOLD, 30))
調整圖片尺寸繼承 ConfigurableCaptchaService 重寫 getWidth()/getHeight()
添加背景圖片自定義 FilterFactory 在 createImage() 中繪製背景
算術題驗證碼實現 WordFactory 生成 "12+5=" 類似字符串,前端提交計算結果
分佈式 Session配合 Spring Session + Redis 共享驗證碼 Token

安全性加固建議

  1. 限流:同一 IP 每分鐘請求驗證碼不超過 N 次
  2. 有效期:Session 設置 5-10 分鐘過期,或用 Redis 存儲 Token 並設置 TTL
  3. 防暴力破解:連續驗證失敗 5 次鎖定賬號/IP 15 分鐘
  4. HTTPS:傳輸層加密防止中間人竊取驗證碼圖片
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved