JCaptcha 是功能強大的驗證碼生成庫,支援圖片驗證碼與音頻驗證碼(如新浪雙重驗證)。本文示範核心配置、引擎封裝、Servlet/Spring MVC 輸出、前端刷新機制。
<dependency>
<groupId>com.octo.captcha</groupId>
<artifactId>jcaptcha</artifactId>
<version>1.0</version>
</dependency>
public class CapchaHelper {
// 配置常量
private static final int MIN_WORD_LENGTH = 4;
private static final int MAX_WORD_LENGTH = 4;
private static final int IMAGE_HEIGHT = 30;
private static final int IMAGE_WIDTH = 130;
private static final int MIN_FONT_SIZE = 15;
private static final int MAX_FONT_SIZE = 15;
private static final String RANDOM_WORD = "0123456789";
private static final Font[] RANDOM_FONT = { new Font("nyala", Font.BOLD, 15), ... };
private static final Color[] RANDOM_COLOR = { Color.WHITE, new Color(255,220,220), ... };
private static ListImageCaptchaEngine captchaEngine;
public static CaptchaEngine getCaptchaEngine(String imgPath) {
if (captchaEngine == null) {
synchronized (CapchaHelper.class) {
if (captchaEngine == null && imgPath != null) {
captchaEngine = new ListImageCaptchaEngine() {
@Override
protected void buildInitialFactories() {
RandomListColorGenerator colorGen = new RandomListColorGenerator(RANDOM_COLOR);
BackgroundGenerator bgGen = new FileReaderRandomBackgroundGenerator(IMAGE_WIDTH, IMAGE_HEIGHT, imgPath);
WordGenerator wordGen = new RandomWordGenerator(RANDOM_WORD);
FontGenerator fontGen = new RandomFontGenerator(MIN_FONT_SIZE, MAX_FONT_SIZE, RANDOM_FONT);
TextDecorator[] decorators = {};
TextPaster textPaster = new DecoratedRandomTextPaster(MIN_WORD_LENGTH, MAX_WORD_LENGTH, colorGen, decorators);
WordToImage wordToImage = new ComposedWordToImage(fontGen, bgGen, textPaster);
addFactory(new GimpyFactory(wordGen, wordToImage));
}
};
}
}
}
return captchaEngine;
}
}
關鍵組件:
BackgroundGenerator:背景圖片生成器(從目錄讀取素材)。WordGenerator:隨機字符生成器。FontGenerator / ColorGenerator:字體/顏色隨機化。TextPaster:文字繪製器(位置、扭曲、干擾線)。WordToImage:合成最終圖片。@WebServlet("/captcha_img")
public class CaptchaServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String bgPath = getServletContext().getRealPath("/WEB-INF/img/captcha"); // 背景圖目錄
CaptchaEngine engine = CapchaHelper.getCaptchaEngine(bgPath);
Captcha captcha = engine.getNextCaptcha();
req.getSession().setAttribute("captcha", captcha); // 存 Session 供驗證
BufferedImage image = (BufferedImage) captcha.getChallenge();
resp.setContentType("image/jpeg");
ImageIO.write(image, "jpg", resp.getOutputStream());
}
}
@Controller
public class CaptchaController {
@GetMapping("/captcha_img")
@ResponseBody
public byte[] captcha(HttpSession session) {
String bgPath = session.getServletContext().getRealPath("/WEB-INF/img/captcha");
CaptchaEngine engine = CapchaHelper.getCaptchaEngine(bgPath);
Captcha captcha = engine.getNextCaptcha();
session.setAttribute("captcha", captcha);
BufferedImage image = (BufferedImage) captcha.getChallenge();
ByteArrayOutputStream bao = new ByteArrayOutputStream();
ImageIO.write(image, "jpg", bao);
return bao.toByteArray();
}
}
<img id="captcha" src="/captcha_img" onclick="refreshCaptchaImg()" />
<script>
function refreshCaptchaImg() {
// 加時間戳參數強制瀏覽器重新請求,避免緩存
var now = new Date();
$("#captcha").attr("src", "/captcha_img?" + now.getTime());
}
</script>
@PostMapping("/login")
public String login(@RequestParam String captchaInput, HttpSession session) {
Captcha captcha = (Captcha) session.getAttribute("captcha");
if (captcha != null && captcha.validateResponse(captchaInput)) {
// 驗證通過
} else {
// 驗證失敗
}
return "redirect:/login";
}
在 /WEB-INF/img/captcha/ 目錄下放置多張 JPEG 圖片作為背景素材,大小不限,引擎會隨機選取並縮放至配置尺寸。
JCaptcha 通過組件化設計(背景、字體、顏色、文字繪製、合成)實現高度可定制的驗證碼生成。結合單例引擎、Session 存儲、前端時間戳刷新,可快速構建安全易用的驗證碼體系。