亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

如何在Java?Web項(xiàng)目中優(yōu)雅地實(shí)現(xiàn)驗(yàn)證碼攔截與校驗(yàn)

 更新時(shí)間:2025年09月16日 08:48:44   作者:微笑聽(tīng)雨。  
驗(yàn)證碼代碼用于防止機(jī)器人提交表單或訪問(wèn)受限頁(yè)面,它是一個(gè)圖像或文本序列,需要輸入才能驗(yàn)證身份,這篇文章主要介紹了如何在Java?Web項(xiàng)目中優(yōu)雅地實(shí)現(xiàn)驗(yàn)證碼攔截與校驗(yàn)的相關(guān)資料,需要的朋友可以參考下

前言

在 Web 開(kāi)發(fā)中,很多網(wǎng)站都會(huì)對(duì)敏感頁(yè)面或公告信息做 驗(yàn)證碼攔截,以防止爬蟲(chóng)或惡意訪問(wèn)。

比如訪問(wèn)某些公告詳情頁(yè)時(shí),必須先輸入驗(yàn)證碼才能繼續(xù)瀏覽。

本文將以一個(gè)實(shí)際的案例為例,演示如何在 Java Web 項(xiàng)目中優(yōu)雅地實(shí)現(xiàn) Filter 攔截 + 驗(yàn)證碼校驗(yàn) + 友好頁(yè)面展示。

1. 需求分析

假設(shè)我們的系統(tǒng)中有以下目錄需要保護(hù):

xzbgg、zhzzsgg、zhzzbhxr、zhzbjggs、zhzzzgg、
xfzbgg、zhfcghxr、zhfcgjg、zhfzzgg、zhzbxx

攔截邏輯:

  • /xxx/index.jhtml 這樣的首頁(yè)不需要攔截;
  • /xxx/12345.jhtml 這樣的詳情頁(yè)必須輸入驗(yàn)證碼才能訪問(wèn);
  • 驗(yàn)證碼通過(guò)后,自動(dòng)跳轉(zhuǎn)回用戶最初請(qǐng)求的頁(yè)面。

2. Filter 攔截實(shí)現(xiàn)

首先我們定義一個(gè) CaptchaFilter,利用 正則表達(dá)式 精準(zhǔn)攔截需要驗(yàn)證的頁(yè)面:

public class CaptchaFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        String uri = req.getRequestURI();

        // 定義需要保護(hù)的路徑前綴
        String[] protectedPaths = {
                "xzbgg", "zhzzsgg", "zhzzbhxr", "zhzbjggs", "zhzzzgg",
                "xfzbgg", "zhfcghxr", "zhfcgjg", "zhfzzgg", "zhzbxx"
        };

        // 匹配 /xxx/數(shù)字.jhtml 的請(qǐng)求
        String pattern = MessageFormat.format(".*/(?:{0})/\\d+\\.jhtml$", String.join("|", protectedPaths));

        if (uri.matches(pattern)) {
            HttpSession session = req.getSession();
            Boolean captchaPassed = (Boolean) session.getAttribute("captchaPassed");

            // 如果驗(yàn)證碼已通過(guò),放行并清理標(biāo)記
            if (Boolean.TRUE.equals(captchaPassed)) {
                chain.doFilter(request, response);
                session.removeAttribute("captchaPassed");
                return;
            }

            // 保存目標(biāo) URL,便于校驗(yàn)成功后跳轉(zhuǎn)回來(lái)
            session.setAttribute("targetUrl", uri);

            // 轉(zhuǎn)發(fā)到驗(yàn)證碼頁(yè)面
            req.getRequestDispatcher("/captcha.html").forward(req, resp);
            return;
        }

        // 其他請(qǐng)求直接放行
        chain.doFilter(request, response);
    }
}

這樣,所有訪問(wèn) /xxx/數(shù)字.jhtml 的請(qǐng)求都會(huì)被攔截,并跳轉(zhuǎn)到驗(yàn)證碼頁(yè)面。

3. web.xml 配置

接著在 web.xml 中注冊(cè) Filter 和兩個(gè) Servlet

  • 一個(gè)生成驗(yàn)證碼圖片(如 JCaptchaServlet);
  • 一個(gè)校驗(yàn)驗(yàn)證碼輸入(我們自定義的 CaptchaCheckServlet)。
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <!-- 驗(yàn)證碼攔截器 -->
    <filter>
        <filter-name>CaptchaFilter</filter-name>
        <filter-class>com.example.filter.CaptchaFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CaptchaFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- 驗(yàn)證碼圖片生成 Servlet (例如 JCaptcha) -->
    <servlet>
        <servlet-name>CaptchaServlet</servlet-name>
        <servlet-class>com.octo.captcha.module.servlet.image.SimpleImageCaptchaServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>CaptchaServlet</servlet-name>
        <url-pattern>/captcha.svl</url-pattern>
    </servlet-mapping>

    <!-- 驗(yàn)證碼校驗(yàn) Servlet -->
    <servlet>
        <servlet-name>CaptchaCheckServlet</servlet-name>
        <servlet-class>com.example.servlet.CaptchaCheckServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>CaptchaCheckServlet</servlet-name>
        <url-pattern>/captcha/check</url-pattern>
    </servlet-mapping>
</web-app>

4. CaptchaCheckServlet 校驗(yàn)邏輯

CaptchaCheckServlet 用來(lái)接收用戶輸入的驗(yàn)證碼,并進(jìn)行校驗(yàn)。

如果校驗(yàn)失敗,重定向回 captcha.html?error=1

public class CaptchaCheckServlet extends HttpServlet {

    private ImageCaptchaService captchaService;

    @Override
    public void init() throws ServletException {
        super.init();
        WebApplicationContext appCtx =
                WebApplicationContextUtils.getWebApplicationContext(getServletContext());
        captchaService = BeanFactoryUtils.beanOfTypeIncludingAncestors(
                appCtx, ImageCaptchaService.class);

        if (captchaService == null) {
            throw new ServletException("CaptchaService 未初始化,請(qǐng)檢查 Spring 配置");
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        HttpSession session = req.getSession();
        String captchaId = session.getId();
        String inputCode = req.getParameter("code");

        boolean passed;
        try {
            passed = captchaService.validateResponseForID(captchaId, inputCode);
        } catch (Exception e) {
            passed = false;
        }

        if (passed) {
            // 驗(yàn)證成功,設(shè)置標(biāo)記并跳轉(zhuǎn)回原頁(yè)面
            session.setAttribute("captchaPassed", true);
            String targetUrl = (String) session.getAttribute("targetUrl");
            session.removeAttribute("targetUrl");

            if (targetUrl != null) {
                resp.sendRedirect(targetUrl);
            } else {
                resp.sendRedirect(req.getContextPath() + "/");
            }
        } else {
            // 驗(yàn)證失敗,重定向并附帶錯(cuò)誤標(biāo)記
            resp.sendRedirect(req.getContextPath() + "/captcha.html?error=1");
        }
    }
}

5. 驗(yàn)證碼頁(yè)面(HTML)

驗(yàn)證碼頁(yè)面保留為 純 HTML,通過(guò) JavaScript 獲取 URL 參數(shù) error 來(lái)顯示錯(cuò)誤提示。

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>請(qǐng)輸入驗(yàn)證碼</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        body {
            font-family: "Microsoft YaHei", Arial, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            margin: 0;
            background: #f4f6f9;
        }
        .captcha-container {
            background: #fff;
            padding: 2rem;
            border-radius: 12px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.1);
            text-align: center;
            width: 300px;
        }
        h2 {
            margin-bottom: 1.2rem;
            font-size: 1.2rem;
            color: #333;
        }
        .error {
            color: red;
            margin-bottom: 1rem;
            display: none;
        }
        img {
            cursor: pointer;
            margin-bottom: 1rem;
            border: 1px solid #ddd;
            border-radius: 6px;
        }
        input[type="text"] {
            width: 100%;
            padding: 10px;
            border: 1px solid #ccc;
            border-radius: 6px;
            font-size: 1rem;
            margin-bottom: 1rem;
        }
        button {
            width: 100%;
            padding: 10px;
            border: none;
            border-radius: 6px;
            background: #007bff;
            color: white;
            font-size: 1rem;
            cursor: pointer;
        }
        button:hover {
            background: #0056b3;
        }
        .tip {
            margin-top: 0.8rem;
            font-size: 0.9rem;
            color: #666;
        }
    </style>
</head>
<body>
<div class="captcha-container">
    <h2>請(qǐng)輸入驗(yàn)證碼</h2>

    <div class="error" id="errorMsg">驗(yàn)證碼錯(cuò)誤,請(qǐng)重新輸入</div>

    <form action="/zhcms/captcha/check" method="post">
        <img src="/zhcms/captcha.svl"
             onclick="this.src='/zhcms/captcha.svl?'+Math.random()"
             alt="驗(yàn)證碼" title="點(diǎn)擊圖片更換驗(yàn)證碼"/>
        <input type="text" name="code" placeholder="請(qǐng)輸入驗(yàn)證碼" required/>
        <button type="submit">提交</button>
        <div class="tip">看不清?點(diǎn)擊圖片刷新驗(yàn)證碼</div>
    </form>
</div>

<script>
    // 從 URL 獲取參數(shù)
    const params = new URLSearchParams(window.location.search);
    if (params.get("error") === "1") {
        document.getElementById("errorMsg").style.display = "block";
    }
</script>
</body>
</html>

頁(yè)面效果如圖所示:

6. 常見(jiàn)問(wèn)題 Q&A

Q1: 為什么驗(yàn)證碼頁(yè)面用 JSP 會(huì)被攔截?

A: 因?yàn)?Filter 攔截了 .jhtml 之外的請(qǐng)求時(shí),轉(zhuǎn)發(fā)到 JSP 也會(huì)觸發(fā)過(guò)濾邏輯,容易形成死循環(huán)。改成 .html 并使用 JavaScript 處理錯(cuò)誤提示即可。

Q2: 驗(yàn)證碼圖片不顯示?

A: 檢查 captcha.svl 是否正確映射到 SimpleImageCaptchaServlet。同時(shí)確認(rèn)瀏覽器是否緩存了圖片,可以通過(guò) ?Math.random() 動(dòng)態(tài)刷新。

Q3: 校驗(yàn)通過(guò)后沒(méi)有跳轉(zhuǎn)回原頁(yè)面?

A: 確保在 Filter 里使用 session.setAttribute("targetUrl", uri) 保存目標(biāo)地址,并在 CaptchaCheckServlet 里取出并重定向。

Q4: 如何擴(kuò)展更多攔截目錄?

A: 只需在 protectedPaths 數(shù)組里新增路徑名即可,例如 "newpath1", "newpath2"

7. 總結(jié)

通過(guò)以上幾個(gè)步驟,我們就實(shí)現(xiàn)了一個(gè)完整的驗(yàn)證碼攔截機(jī)制:

  1. Filter 攔截:利用正則表達(dá)式精確攔截 /xxx/數(shù)字.jhtml 的請(qǐng)求;
  2. 驗(yàn)證碼校驗(yàn):用戶輸入后由 CaptchaCheckServlet 校驗(yàn),成功后跳轉(zhuǎn)回原始頁(yè)面;
  3. 用戶體驗(yàn)優(yōu)化:驗(yàn)證碼頁(yè)面保持 HTML,支持錯(cuò)誤提示,UI 簡(jiǎn)潔美觀;
  4. 常見(jiàn)問(wèn)題處理:避免死循環(huán),解決驗(yàn)證碼圖片緩存問(wèn)題。

這種實(shí)現(xiàn)方式簡(jiǎn)單清晰、可維護(hù)性強(qiáng),非常適合需要在項(xiàng)目中批量攔截頁(yè)面并加上驗(yàn)證碼驗(yàn)證的場(chǎng)景。

到此這篇關(guān)于如何在Java Web項(xiàng)目中優(yōu)雅地實(shí)現(xiàn)驗(yàn)證碼攔截與校驗(yàn)的文章就介紹到這了,更多相關(guān)Java Web驗(yàn)證碼攔截與校驗(yàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論