本文提供一個生產級的 Spring MVC @RestController,生成帶干擾線、隨機顏色、可配置長度的 JPEG 驗證碼圖片,並將驗證碼存入 HttpSession 供後續表單驗證使用。
@RestController
@RequestMapping("")
public class ImgCodeController {
@Autowired
private RedisTemplate cache; // 可選:分散式 Session 支援
private int width = 90;
private int height = 30;
private int codeCount = 4;
private int xx = 15;
private int fontHeight = 18;
private int codeY = 16;
private char[] codeSequence = {
'A','B','C','D','E','F','G','H','I','J','K','L','M',
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'0','1','2','3','4','5','6','7','8','9'
};
@RequestMapping("/checkCode")
protected void doGetCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 1. 禁用快取
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.setContentType("image/jpeg");
// 2. 建立圖片緩衝區
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
Random random = new Random();
// 3. 填充背景
g.setColor(getRandColor(200, 250));
g.fillRect(0, 0, width, height);
// 4. 設定字體
g.setFont(new Font("Times New Roman", Font.PLAIN, fontHeight));
// 5. 畫邊框
g.setColor(new Color(20, 20, 20));
g.drawRect(0, 0, width - 1, height - 1);
// 6. 畫干擾線
g.setColor(getRandColor(160, 200));
for (int i = 0; i < 155; i++) {
int x = random.nextInt(width);
int y = random.nextInt(height);
int xl = random.nextInt(12);
int yl = random.nextInt(12);
g.drawLine(x, y, x + xl, y + yl);
}
// 7. 生成並繪製驗證碼字元
StringBuffer randomCode = new StringBuffer();
for (int i = 0; i < codeCount; i++) {
String code = String.valueOf(codeSequence[random.nextInt(codeSequence.length)]);
int red = 20 + random.nextInt(110);
int green = 20 + random.nextInt(110);
int blue = 20 + random.nextInt(110);
g.setColor(new Color(red, green, blue));
g.drawString(code, (i + 1) * xx, codeY);
randomCode.append(code);
}
// 8. 存入 Session
HttpSession session = request.getSession();
session.setAttribute("code", randomCode.toString());
// 9. 輸出圖片
g.dispose();
ServletOutputStream sos = response.getOutputStream();
ImageIO.write(image, "jpeg", sos);
sos.close();
}
private Color getRandColor(int fc, int bc) {
Random random = new Random();
if (fc > 255) fc = 255;
if (bc > 255) bc = 255;
int r = fc + random.nextInt(bc - fc);
int g = fc + random.nextInt(bc - fc);
int b = fc + random.nextInt(bc - fc);
return new Color(r, g, b);
}
// Getter/Setter 省略...
}
BufferedImage.TYPE_INT_RGB 建立記憶體圖片,Graphics 進行繪圖操作。drawString 繪製於計算位置。HttpSession,鍵為 "code"。ImageIO.write(image, "jpeg", outputStream) 直接寫入 HTTP 回應串流。<img src="/checkCode" id="captchaImg" onclick="this.src='/checkCode?t='+Date.now()" />
<input type="text" name="captcha" />
點擊圖片刷新(加時間戳避免瀏覽器快取)。表單提交時後端比對 session.getAttribute("code") 與用戶輸入(忽略大小寫)。
Google Kaptcha 或 SimpleCaptcha 成熟庫,支援更多字型、噪點、扭曲效果。