<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version> <!-- 現代維護版本 -->
</dependency>
注意: 原 com.google.code.kaptcha 已停止維護,建議使用社區 Fork 版 com.github.penggle:kaptcha,API 完全相容。
kaptcha:
border: no
border.thickness: 0
textproducer:
font.color: black
font.size: 35
char.length: 4
char.string: "0123456789"
font.names: "Arial,Courier"
char.space: 10
image.width: 150
image.height: 50
background.clear.from: "255,255,255"
background.clear.to: "255,255,255"
noise.impl: "com.google.code.kaptcha.impl.NoNoise"
session.key: "KAPTCHA_SESSION_KEY" # Session 屬性名
KaptchaServlet 至 /kaptcha.jpg<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>no</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.textproducer.font.size</param-name>
<param-value>35</param-value>
</init-param>
<init-param>
<param-name>kaptcha.image.width</param-name>
<param-value>150</param-value>
</init-param>
<init-param>
<param-name>kaptcha.image.height</param-name>
<param-value>50</param-value>
</init-param>
<init-param>
<param-name>kaptcha.textproducer.char.string</param-name>
<param-value>0123456789</param-value>
</init-param>
<init-param>
<param-name>kaptcha.noise.impl</param-name>
<param-value>com.google.code.kaptcha.impl.NoNoise</param-value>
</init-param>
<!-- 更多參數參考 Kaptcha 官方文檔 -->
</servlet>
<servlet-mapping>
<servlet-name>Kaptcha</servlet-name>
<url-pattern>/kaptcha.jpg</url-pattern>
</servlet-mapping>
<img id="captchaImg" src="/kaptcha.jpg" width="150" height="50"
style="cursor:pointer; vertical-align:middle;"
title="點擊刷新" alt="驗證碼" />
<input type="text" name="captcha" placeholder="輸入驗證碼" />
<script>
document.getElementById('captchaImg').onclick = function() {
this.src = '/kaptcha.jpg?' + Date.now(); // 防緩存
};
</script>
@PostMapping("/login")
public Result login(@RequestParam String username,
@RequestParam String password,
@RequestParam String captcha,
HttpSession session) {
String expected = (String) session.getAttribute(
com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
if (expected == null || !expected.equalsIgnoreCase(captcha)) {
return Result.error("驗證碼錯誤或已過期");
}
// 驗證通過,移除防重放
session.removeAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
// 後續業務邏輯...
return Result.ok();
}
kaptcha:
textproducer:
char.string: "ABCDEFGHJKLMNPQRSTUVWXYZ23456789" # 排除易混淆字符
char.length: 5
@Bean
public DefaultKaptcha customKaptcha() {
DefaultKaptcha kaptcha = new DefaultKaptcha();
Properties props = new Properties();
props.setProperty("kaptcha.textproducer.impl", "com.example.ChineseTextProducer");
kaptcha.setConfig(new Config(props));
return kaptcha;
}
public class MathTextProducer implements TextProducer {
@Override
public String getText() {
int a = (int)(Math.random() * 20) + 1;
int b = (int)(Math.random() * 20) + 1;
return a + " + " + b + " = ?"; // Session 需存儲答案 a+b
}
@Override
public String getText(String s) { return getText(); }
}
| 現象 | 原因 | 解決 |
|---|---|---|
| 圖片不顯示 / 404 | Servlet 映射路徑錯誤 | 檢查 /kaptcha.jpg 與 <img src> 一致 |
| Session 取值為 null | Session 過期或跨域 | 確保前後端同域、Session 有效期足夠、未禁用 Cookie |
| 驗證碼總是錯誤 | 大小寫敏感 / 空白字符 | 使用 equalsIgnoreCase、trim() |
| 中文亂碼 | 字體不支援中文 | 設定 font.names 為支援中文字體 (如 "Microsoft JhengHei") |
| 高併發下圖片生成慢 | 預設實現同步 | 考慮 Redis 儲存驗證碼 + 異步生成、或換用簡單算術驗證碼 |
Kaptcha 作為輕量級驗證碼方案,整合 Spring 極其簡單。生產環境請注意:**字符集去混淆、Session 及時清理、失敗次數限制、必要時升級更強驗證碼**。Spring Boot 專案僅需引入依賴 + YAML 配置即可零代碼接入。