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

Java Web 防盜鏈實戰:基於 Referer 檢測的報表訪問控制

     編輯:Java 相關知識

什麼是防盜鏈?

防盜鏈是指防止未授權網站通過直接引用你的資源鏈接(圖片、報表、視頻等)消耗你的帶寬與服務器資源。核心原理是檢查 HTTP 請求頭中的 Referer 字段,判斷請求來源是否在白名單內。

Referer 頭詳解

  • 含義:標識請求發起頁面的 URL,由瀏覽器自動添加。
  • 空 Referer 場景:用戶直接在瀏覽器地址欄輸入 URL、HTTPS 頁面引用 HTTP 資源、瀏覽器隱私模式/插件攔截、移動端 App 內嵌 WebView 等。
  • 策略選擇:允許空 Referer 便於用戶直接訪問但防禦較弱;拒絕空 Referer 安全性高但可能誤傷正常用戶。

實戰場景:FineReport 報表集成權限控制

業務背景:報表服務部署在 Tomcat,前端門戶系統負責登錄鑒權。需確保報表鏈接僅能從門戶頁面跳轉打開,防止用戶複製鏈接直接訪問或第三方網站盜用。

方案實現:Servlet Filter 過濾器

1. 核心過濾器代碼

package com.fr.security;

import jakarta.servlet.*;
import jakarta.servlet.http.*;
import java.io.IOException;

public class ReportAntiHotlinkFilter implements Filter {
    // 允許的來源域名白名單(支援通配符前綴匹配)
    private static final String[] ALLOWED_REFERER_PREFIXES = {
        "https://portal.mycompany.com/",
        "https://portal.mycompany.com/",
        "https://localhost:8080/portal/"
    };
    // 非法訪問導向頁面
    private static final String DENIED_URL = "/login.jsp?error=hotlink";

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;

        String referer = req.getHeader("Referer");
        boolean allowed = false;

        if (referer != null) {
            for (String prefix : ALLOWED_REFERER_PREFIXES) {
                if (referer.startsWith(prefix)) {
                    allowed = true;
                    break;
                }
            }
        }

        if (allowed) {
            chain.doFilter(req, resp); // 合法來源,放行
        } else {
            // 非法來源:記錄審計日誌
            String clientIp = req.getRemoteAddr();
            String requestedUri = req.getRequestURI();
            log.warn("防盜鏈攔截: IP={}, Referer={}, URI={}", clientIp, referer, requestedUri);
            
            // 重定向到登錄/錯誤頁
            resp.sendRedirect(req.getContextPath() + DENIED_URL);
        }
    }
}

2. web.xml 配置(或 Spring Boot 中 @WebFilter)

<filter>
    <filter-name>ReportAntiHotlinkFilter</filter-name>
    <filter-class>com.fr.security.ReportAntiHotlinkFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>ReportAntiHotlinkFilter</filter-name>
    <url-pattern>/ReportServer</url-pattern> <!-- FineReport 核心入口 -->
</filter-mapping>

測試驗證矩陣

場景Referer 值預期結果
門戶頁面點擊報表鏈接https://portal.mycompany.com/report-list✅ 放行
第三方網站嵌入 iframehttps://evil.com/dashboard❌ 攔截跳轉登錄頁
用戶瀏覽器直接輸入報表 URLnull (空)❌ 攔截(或按策略放行)
郵件/文檔中點擊鏈接郵件客戶端域名❌ 攔截(需加入白名單才放行)

進階增強方案

  1. 簽名鏈接(Token 機制):門戶生成帶時間戳、隨機數、HMAC-SHA256 簽名的一次性報表 URL,報表服務驗證簽名有效性,徹底解決 Referer 可偽造/不可靠問題。
  2. 單點登錄(SSO)集成:過濾器中檢查 Session/Token,未登錄重定向至統一登錄頁,登錄成功回跳原報表 URL。
  3. 數據級權限:在報表查詢 SQL 中動態注入當前用戶的機構/角色過濾條件,實現「同一報表、不同人看不同數據」。

注意事項

  • Referer 头可被客戶端偽造或攔截器移除,不可作為唯一安全防線,需結合 Token/SSO。
  • HTTPS 頁面引用 HTTP 資源時瀏覽器不發送 Referer(降級策略),建議全站 HTTPS。
  • 過濾器順序:應在編碼過濾器、登錄檢查過濾器之前執行,避免漏攔截靜態資源請求。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved