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

基於 HttpServletResponseWrapper 的響應內容過濾器:敏感詞替換與非法內容攔截實戰

     編輯:Java 綜合教學

業務背景

Web 應用需在響應輸出到瀏覽器前,統一攔截並替換敏感詞(如廣告詞、違禁詞、錯別字修正等)。核心思路:自定義 Response 包裝類緩存輸出內容 → Filter 中替換 → 再寫入原始 Response。

核心組件設計

1. 緩存響應包裝類:HttpCharacterResponseWrapper

public class HttpCharacterResponseWrapper extends HttpServletResponseWrapper {
    private final CharArrayWriter buffer = new CharArrayWriter();

    public HttpCharacterResponseWrapper(HttpServletResponse response) {
        super(response);
    }

    @Override
    public PrintWriter getWriter() {
        return new PrintWriter(buffer); // 將輸出導向內存緩存
    }

    public CharArrayWriter getBuffer() {
        return buffer;
    }
}

關鍵點:覆寫 getWriter() 返回指向 CharArrayWriter 的 PrintWriter,實現「攔截輸出、內存緩存」。

2. 內容替換過濾器:OutputReplaceFilter

@WebFilter(filterName = "OutputReplaceFilter", urlPatterns = "*.jsp")
public class OutputReplaceFilter implements Filter {

    private Properties sensitiveWords = new Properties();

    @Override
    public void init(FilterConfig config) throws ServletException {
        String file = config.getInitParameter("file"); // e.g. /WEB-INF/sensitive.properties
        String realPath = config.getServletContext().getRealPath(file);
        try (FileInputStream fis = new FileInputStream(realPath)) {
            sensitiveWords.load(fis);
        } catch (IOException e) {
            throw new ServletException("加載敏感詞配置失敗", e);
        }
    }

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

        HttpCharacterResponseWrapper wrapper = new HttpCharacterResponseWrapper((HttpServletResponse) resp);
        chain.doFilter(req, wrapper); // 讓後續鏈路寫入 wrapper

        String content = wrapper.getBuffer().toString(); // 取出完整響應文本

        // 遍歷替換
        for (Object keyObj : sensitiveWords.keySet()) {
            String key = (String) keyObj;
            content = content.replace(key, sensitiveWords.getProperty(key));
        }

        // 寫回原始響應
        PrintWriter out = resp.getWriter();
        out.write(content);
        out.println("<!-- Generated at " + new Date() + " -->");
    }

    @Override
    public void destroy() { /* no-op */ }
}

3. 敏感詞配置:/WEB-INF/sensitive.properties

# 修正類
Chna = China
www.baidu.com.cn = www.baidu.com

# 替換類
色情 = **
賭博 = **
情色 = **

4. web.xml 註冊(非 Spring Boot 環境)

<filter>
    <filter-name>OutputReplaceFilter</filter-name>
    <filter-class>com.yzj.filter.OutputReplaceFilter</filter-class>
    <init-param>
        <param-name>file</param-name>
        <param-value>/WEB-INF/sensitive.properties</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>OutputReplaceFilter</filter-name>
    <url-pattern>*.jsp</url-pattern>
</filter-mapping>

運行效果驗證

JSP 頁面輸出:

Chna
色情
賭博
情色
www.baidu.com.cn

瀏覽器實際接收:

China
**
**
**
www.baidu.com

進階優化與注意事項

維度建議
性能大響應體建議用 StringBuilder 或流式替換(如 Aho-Corasick 多模匹配),避免多次 String.replace 產生大量臨時對象。
編碼確保 request/response.setCharacterEncoding(\"UTF-8\"),Properties 文件存 UTF-8,防止中文亂碼。
範圍僅攔截文本類響應(HTML/JSON/XML),二進制流(圖片/下載)應排除,可在 Filter 中判斷 Content-Type。
Spring Boot改用 @Component + FilterRegistrationBean 註冊,屬性注入用 @Value 讀取 YAML/Properties。
XSS 防護本方案可順帶做 HTML 轉義,但專業場景建議引入 OWASP Java HTML Sanitizer。

原理總結

  1. Filter 創建 偽裝 Response(Wrapper)傳給 Servlet 鏈路。
  2. Servlet 寫入 Wrapper → 內容實際進入 CharArrayWriter 內存緩存。
  3. Filter 從緩存取出完整字符串 → 遍歷替換敏感詞。
  4. Filter 通過原始 Response 的 getWriter() 寫出最終內容給瀏覽器。

此模式屬於裝飾器模式在 Servlet 規範中的經典應用,同樣可用於響應壓縮、加密、簽名、日誌記錄等橫切關注點處理。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved