不依賴第三方庫,使用 java.awt 繪製干擾線、隨機字符,輸出 JPEG 流,存入 Session 驗證。
<%@ taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core" %>
<c:set var="ctx" value="${pageContext.request.contextPath}"/>
<form id="loginform" method="post">
<table>
<tr><td>用戶名:</td><td><input type="text" name="loginname"/></td></tr>
<tr><td>密碼:</td><td><input type="password" name="password"/></td></tr>
<tr>
<td>驗證碼:</td>
<td><input type="text" name="code"/></td>
<td><img id="codeImg" alt="驗證碼" src="${ctx}/admin/code" onclick="changeImg()"/></td>
</tr>
</table>
</form>
<script>
function changeImg() {
var img = $("#codeImg");
var src = img.attr("src");
img.attr("src", src + (src.indexOf("?") >= 0 ? "&" : "?") + "t=" + new Date().getTime());
}
</script>
@Controller
@RequestMapping("/admin")
public class CodeController {
private int width = 90, height = 20, codeCount = 4;
private int xx = 15, fontHeight = 18, codeY = 16;
private char[] codeSequence = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray();
@RequestMapping("/code")
public void getCode(HttpServletRequest req, HttpServletResponse resp) throws IOException {
BufferedImage buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = buffImg.createGraphics();
Random random = new Random();
// 背景
g.setColor(Color.WHITE);
g.fillRect(0, 0, width, height);
// 字體
g.setFont(new Font("Fixedsys", Font.BOLD, fontHeight));
// 邊框
g.setColor(Color.BLACK);
g.drawRect(0, 0, width - 1, height - 1);
// 干擾線
g.setColor(Color.BLACK);
for (int i = 0; i < 40; i++) {
int x = random.nextInt(width);
int y = random.nextInt(height);
g.drawLine(x, y, x + random.nextInt(12), y + random.nextInt(12));
}
// 生成驗證碼
StringBuilder randomCode = new StringBuilder();
for (int i = 0; i < codeCount; i++) {
String code = String.valueOf(codeSequence[random.nextInt(codeSequence.length)]);
g.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
g.drawString(code, (i + 1) * xx, codeY);
randomCode.append(code);
}
// 存入 Session
req.getSession().setAttribute("code", randomCode.toString());
// 禁止緩存
resp.setHeader("Pragma", "no-cache");
resp.setHeader("Cache-Control", "no-cache");
resp.setDateHeader("Expires", 0);
resp.setContentType("image/jpeg");
ImageIO.write(buffImg, "jpeg", resp.getOutputStream());
}
}
@RequestMapping("/login")
public @ResponseBody JsonResult login(HttpServletRequest req, String loginname, String password, String code) {
String sessionCode = (String) req.getSession().getAttribute("code");
if (sessionCode == null || !sessionCode.equalsIgnoreCase(code)) {
return JsonResult.error("驗證碼不正確!");
}
// 後續業務驗證...
return JsonResult.success();
}
equalsIgnoreCase 忽略大小寫