首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Spring MVC 實現驗證碼生成與驗證:Kaptcha 替代方案與手工繪圖完整代碼

     編輯:Java 綜合教學

Spring MVC 手工實現圖形驗證碼生成與驗證

不依賴第三方庫,使用 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 生成驗證碼

@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();
}

四、優化建議

  • 使用 Google Kaptcha 或 SimpleCaptcha 庫,功能更豐富(中文、噪點、扭曲)
  • 生產環境建議:驗證碼存入 Redis、設定過期時間、限制嘗試次數
  • 前端點擊換圖加時間戳防緩存
  • 驗證時使用 equalsIgnoreCase 忽略大小寫
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved