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

Java 驗證碼生成實戰(下):JCaptcha、Kaptcha、中文/算術驗證碼與雙因子認證

     編輯:Java 相關知識

方案三:JCaptcha 開源組件

JCaptcha (Java CAPTCHA) 支援圖形/語音驗證碼,需三個 JAR:jcaptcha-2.0-all.jar、commons-collections-3.2.jar、commons-logging-1.1.1.jar。

web.xml 配置

<servlet>
  <servlet-name>jcaptcha</servlet-name>
  <servlet-class>com.octo.captcha.module.servlet.image.SimpleImageCaptchaServlet</servlet-class>
</servlet>
<servlet>
  <servlet-name>submit</servlet-name>
  <servlet-class>com.octo.captcha.module.servlet.image.sample.SubmitActionServlet</servlet-class>
</servlet>
<servlet-mapping><servlet-name>jcaptcha</servlet-name><url-pattern>/jcaptcha.jpg</url-pattern></servlet-mapping>
<servlet-mapping><servlet-name>submit</servlet-name><url-pattern>/submit.action</url-pattern></servlet-mapping>

驗證 Servlet

public class SubmitActionServlet extends HttpServlet {
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        String userCaptchaResponse = req.getParameter("japtcha");
        boolean passed = SimpleImageCaptchaServlet.validateResponse(req, userCaptchaResponse);
        resp.getWriter().write(passed ? "captcha passed" : "captcha failed");
        resp.getWriter().write("<br/><a href='index.jsp'>Try again</a>");
    }
}

前端調用

<img src="jcaptcha.jpg" />
<input type="text" name="japtcha" />
<input type="submit" />

方案四:Kaptcha (Google 開源) - 功能最豐富

核心 KaptchaServlet 生成圖片並將驗證碼存入 Session (KAPTCHA_SESSION_KEY)。

web.xml 詳細配置 (支援高度客製化)

<servlet>
  <servlet-name>Kaptcha</servlet-name>
  <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
  <init-param><param-name>kaptcha.border</param-name><param-value>yes</param-value></init-param>
  <init-param><param-name>kaptcha.border.color</param-name><param-value>black</param-value></init-param>
  <init-param><param-name>kaptcha.image.width</param-name><param-value>120</param-value></init-param>
  <init-param><param-name>kaptcha.image.height</param-name><param-value>40</param-value></init-param>
  <init-param><param-name>kaptcha.textproducer.font.names</param-name><param-value>Arial, Courier</param-value></init-param>
  <init-param><param-name>kaptcha.textproducer.font.size</param-name><param-value>30</param-value></init-param>
  <init-param><param-name>kaptcha.textproducer.font.color</param-name><param-value>black</param-value></init-param>
  <init-param><param-name>kaptcha.textproducer.char.length</param-name><param-value>4</param-value></init-param>
  <init-param><param-name>kaptcha.noise.impl</param-name><param-value>com.google.code.kaptcha.impl.DefaultNoise</param-value></init-param>
  <init-param><param-name>kaptcha.obscurificator.impl</param-name><param-value>com.google.code.kaptcha.impl.WaterRipple</param-value></init-param>
  <init-param><param-name>kaptcha.session.key</param-name><param-value>KAPTCHA_SESSION_KEY</param-value></init-param>
</servlet>
<servlet-mapping><servlet-name>Kaptcha</servlet-name><url-pattern>/randomcode.jpg</url-pattern></servlet-mapping>

前端:點擊刷新防緩存

<img id="captcha" src="randomcode.jpg" onclick="this.src='randomcode.jpg?t='+new Date().getTime()" />

後端驗證

String k = (String) session.getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
String input = request.getParameter("r");
if (k.equals(input)) out.print("true");

進階客製:中文驗證碼

繼承 DefaultTextCreator 並覆寫 getText():

public class ChineseText extends Configurable implements TextProducer {
    public String getText() {
        int len = getConfig().getTextProducerCharLength();
        String[] chs = {"我","愛","扎","瓦","和","賣","塞","扣"};
        Random r = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i=0; i<len; i++) sb.append(chs[r.nextInt(chs.length)]);
        return sb.toString();
    }
}

web.xml 指定:<param-name>kaptcha.textproducer.impl</param-name><param-value>ChineseText</param-value>

進階客製:算術運算驗證碼

繼承 KaptchaServlet 覆寫 doGet():

public class KaptchaServlet extends HttpServlet {
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        String capText = kaptchaProducer.createText(); // 如 "3+5=?"
        String[] parts = capText.split("[+=]");
        int result = Integer.parseInt(parts[0]) + Integer.parseInt(parts[1]);
        req.getSession().setAttribute(sessionKeyValue, String.valueOf(result));
        BufferedImage bi = kaptchaProducer.createImage(capText);
        ImageIO.write(bi, "jpg", resp.getOutputStream());
    }
}

web.xml 指定自訂 Servlet 類。

安全性思考:驗證碼非銀彈

  • 傳統圖形驗證碼易被 OCR/深度學習破解。
  • 個人信息洩露導致社工攻擊繞過驗證碼(如騙取短信碼)。

雙因子認證 (2FA) - 更強防護

定義:結合「你知道的」(密碼)+「你擁有的」(手機/Token/生物特徵)。

  • TOTP (時間同步):Google Authenticator、Authy,每 30 秒生成動態碼。
  • 短信/語音碼:傳送一次性密碼 (OTP) 到受信設備。
  • 硬體 Token:RSA SecurID、DKEY 等。
  • 生物識別:指紋、人臉、聲紋。

核心優勢:動態參數(時間/事件)+ 密鑰 算法生成一次性密碼,不可預測、不可重放。

總結

從簡單繪圖到 JCaptcha/Kaptcha 組件,再到中文/算術客製化,驗證碼形式日益豐富。但單靠驗證碼不足,生產環境應採用雙因子認證、風控引擎、行為分析等多層防護體系。

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