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

仿 12306 圖片驗證碼實現:圖片合成、前端點擊驗證與坐標判斷完整流程

     編輯:Java 綜合教學

仿 12306 圖片驗證碼實現:圖片合成、前端點擊驗證與坐標判斷完整流程

本文實現類 12306 行為驗證碼:服務端從分類目錄隨機抽取 8 張圖片合成一張大圖,隨機指定一類作為驗證目標;前端展示大圖,用戶點擊選擇目標圖片,提交點擊坐標;後端根據坐標映射判斷是否命中目標類別。

服務端核心流程

  1. 隨機選圖:從二級分類目錄各隨機抽 1 張,共 8 張,去重,記錄分類名稱數組 tips[8]。
  2. 確定目標類別:從 tips 中隨機選一個 tip,記錄該類別在 8 張圖中的位置(1-8),存入 Session。
  3. 圖片合成:使用 BufferedImage.setRGB 將 8 張 200x200 小圖拼成 800x400 大圖(兩行四列),輸出 JPEG 流。
  4. 前端展示:JSP 加載大圖,用戶點擊記錄相對坐標(原點為第 8 圖右下角),提交逗號分隔的 x||y 序列。
  5. 坐標驗證:後端解析坐標,判斷落在哪幾個小圖區域(1-8),與 Session 中目標位置比對,全中即通過。

關鍵代碼片段

1. 選圖與目標確定

public static List<Object> getEightImages() {
    List<String> paths = new ArrayList<>();
    File[] finalImages = new File[8];
    String[] tips = new String[8];
    for (int i = 0; i < 8; i++) {
        File secDir = getRandomSubDir(); // 隨機二級目錄
        tips[i] = secDir.getName();
        File img = getRandomFile(secDir);
        img = dropSameImage(img, paths, tips, i); // 去重
        paths.add(img.getPath());
        finalImages[i] = img;
    }
    return Arrays.asList(finalImages, tips);
}

public static List<Object> getLocation(String[] tips) {
    String tip = tips[new Random().nextInt(8)]; // 隨機目標類別
    List<Object> loc = new ArrayList<>();
    loc.add(tip);
    for (int i = 0; i < 8; i++) if (tip.equals(tips[i])) loc.add(i + 1); // 1-based
    return loc;
}

2. 圖片合成

public static void mergeImage(File[] imgs, HttpServletResponse resp) throws IOException {
    BufferedImage big = new BufferedImage(800, 400, BufferedImage.TYPE_INT_BGR);
    for (int i = 0; i < 8; i++) {
        BufferedImage src = ImageIO.read(imgs[i]);
        int[] rgb = src.getRGB(0, 0, src.getWidth(), src.getHeight(), null, 0, src.getWidth());
        if (i < 4) big.setRGB(i * 200, 0, 200, 200, rgb, 0, 200);
        else big.setRGB((i - 4) * 200, 200, 200, 200, rgb, 0, 200);
    }
    ImageIO.write(big, "jpg", resp.getOutputStream());
}

3. Controller 邏輯

List<Object> obj = ImageHelper.getEightImages();
File[] imgs = (File[]) obj.get(0);
String[] tips = (String[]) obj.get(1);
List<Object> loc = ImageHelper.getLocation(tips);
session.setAttribute("tip", loc.get(0)); // 目標類別
loc.remove(0);
session.setAttribute("locations", loc); // 目標位置列表
ImageHelper.mergeImage(imgs, response);

4. 前端點擊與刷新

// 點擊記錄坐標
$('#bigPic').click(e => {
    let x = e.offsetX - 400; // 原點調整
    let y = 200 - e.offsetY;
    coords.push(x + '||' + y);
    // 添加標記 div...
});

// 刷新驗證碼(AJAX + Blob)
function refresh() {
    fetch('/identify').then(r => r.blob()).then(blob => {
        bigPic.src = URL.createObjectURL(blob);
    });
}

5. 坐標驗證邏輯

public List<Integer> isPass(String coords) {
    List<Integer> clicked = new ArrayList<>();
    for (String xy : coords.split(",")) {
        int x = Integer.parseInt(xy.split("\\|\\|")[0]);
        int y = Integer.parseInt(xy.split("\\|\\|")[1]);
        // 根據 200x200 區域判斷圖片編號 1-8
        if (x > -75 && x <= 0) {
            if (y > -75 && y <= 0) clicked.add(8);
            else if (y >= -150 && y <= -75) clicked.add(4);
        } else if (x > -150 && x <= -75) { ... }
        // ... 其餘區域
    }
    return clicked;
}
// 對比 clicked 與 session.locations

安全性增強建議

  • 生成大圖後增加高斯模糊、干擾線、隨機噪點,防止機器視覺識別。
  • 分類圖片庫定期更新,增加樣本多樣性。
  • 限制單 IP 請求頻率,防暴力破解。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved