| 類型 | 安全性 | 用戶體驗 | 實現複雜度 | 適用場景 |
|---|---|---|---|---|
| 靜態 JPG | 低(易 OCR 識別) | 一般 | 低 | 低安全需求 |
| 氣泡/干擾線 JPG | 中 | 好 | 中 | 通用業務 |
| 動態 GIF | 高(幀動畫干擾 OCR) | 佳 | 中 | 高安全需求 |
| 行為/滑塊驗證 | 極高 | 最佳 | 高 | 核心業務(登錄/支付) |
使用開源工具類 vcode-sojson.com(內含 Captcha、GifCaptcha、SpecCaptcha 等實現)。
@RestController
@RequestMapping("/captcha")
public class CaptchaController {
private static final Logger log = LoggerFactory.getLogger(CaptchaController.class);
/**
* 獲取 GIF 動畫驗證碼
* 寬 146px,高 33px,4 位字符
*/
@GetMapping("/gif")
public void getGifCode(HttpServletResponse response, HttpServletRequest request) {
try {
// 禁用緩存
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.setContentType("image/gif");
// 生成 GIF 驗證碼
Captcha captcha = new GifCaptcha(146, 33, 4);
captcha.out(response.getOutputStream());
// 存入 Session(轉小寫統一驗證)
HttpSession session = request.getSession(true);
session.setAttribute("_code", captcha.text().toLowerCase());
} catch (Exception e) {
log.error("生成 GIF 驗證碼異常", e);
}
}
/**
* 獲取 JPG 氣泡/干擾線驗證碼
*/
@GetMapping("/jpg")
public void getJpgCode(HttpServletResponse response, HttpServletRequest request) {
try {
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.setContentType("image/jpeg");
// SpecCaptcha: 氣泡風格 / 可選 SpecCaptcha(寬, 高, 位數, 字體類型)
Captcha captcha = new SpecCaptcha(146, 33, 4);
captcha.out(response.getOutputStream());
HttpSession session = request.getSession(true);
session.setAttribute("_code", captcha.text().toLowerCase());
} catch (Exception e) {
log.error("生成 JPG 驗證碼異常", e);
}
}
/**
* 驗證碼校驗接口
*/
@PostMapping("/verify")
public Result verify(@RequestParam String code, HttpServletRequest request) {
HttpSession session = request.getSession(false);
String sessionCode = (String) session?.getAttribute("_code");
if (sessionCode != null && sessionCode.equals(code.toLowerCase())) {
session.removeAttribute("_code"); // 一次性使用
return Result.success();
}
return Result.error("驗證碼錯誤或已過期");
}
}
<!-- HTML -->
<div class="captcha-container">
<img id="captchaImg" src="/captcha/gif" alt="驗證碼" style="cursor:pointer;" />
<span class="refresh" onclick="refreshCaptcha()">看不清?換一張</span>
</div>
<input type="text" id="captchaInput" placeholder="請輸入驗證碼" />
<script>
function refreshCaptcha() {
// 加時間戳防止瀏覽器緩存
document.getElementById('captchaImg').src = '/captcha/gif?t=' + Date.now();
}
// 表單提交時驗證
$('#loginForm').submit(function() {
var code = $('#captchaInput').val();
$.post('/captcha/verify', {code: code}, function(res) {
if (!res.success) {
alert(res.message);
refreshCaptcha();
return false;
}
// 繼續登錄邏輯...
});
});
</script>
完整工具類源碼:vcode-sojson.com(jb51.net).rar
包含:Captcha.java(抽象基類)、GifCaptcha.java、SpecCaptcha.java、字體文件、示例代碼。
動態 GIF 驗證碼通過幀動畫干擾顯著提升安全性,配合氣泡 JPG 版本可根據業務靈活切換。核心要點:禁用緩存頭、Session/Radis 存儲驗證碼、前端點擊刷新機制、一次性驗證後銷毀。建議關鍵業務升級至滑塊/行為驗證獲得更好體驗與安全平衡。