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

Java 獲取 HttpServletRequest Header 完整指南

     編輯:Java 相關知識

HTTP Header 攜帶客戶端信息、認證憑證、代理鏈路、緩存控制等關鍵元數據。本文系統講解在 Servlet、Spring MVC、JSP 中獲取 Header 的多種方式,含單值/多值獲取、遍歷所有 Header、常見 Header 含義、偽造風險與防範。

核心 API:HttpServletRequest


// 單值獲取 (取首個)
String userAgent = request.getHeader("User-Agent");
String token = request.getHeader("Authorization");

// 多值獲取 (如多個 Cookie、X-Forwarded-For)
Enumeration headers = request.getHeaders("X-Forwarded-For");
while (headers.hasMoreElements()) {
    System.out.println(headers.nextElement());
}

// 獲取所有 Header 名稱
Enumeration names = request.getHeaderNames();
while (names.hasMoreElements()) {
    String name = names.nextElement();
    String value = request.getHeader(name); // 取首個
    System.out.println(name + ": " + value);
}

Spring MVC 中優雅獲取

方式 1:@RequestHeader 參數綁定


@GetMapping("/api/user")
public UserInfo getUser(
    @RequestHeader("User-Agent") String ua,
    @RequestHeader(value = "X-Request-Id", required = false) String requestId,
    @RequestHeader Map allHeaders // 全量綁定為 Map
) {
    // 自動處理缺失、類型轉換
}

方式 2:注入 HttpServletRequest (不推薦耦合)


@Autowired HttpServletRequest request; // 請求作用域 Bean,線程安全

@GetMapping("/legacy")
public void legacy() {
    String ua = request.getHeader("User-Agent");
}

方式 3:ControllerAdvice 統一提取 (跨域、日誌、認證)


@ControllerAdvice
public class HeaderInterceptor {
    private static final Logger log = LoggerFactory.getLogger(HeaderInterceptor.class);

    @ModelAttribute
    public void extractCommonHeaders(HttpServletRequest request, Model model) {
        String traceId = request.getHeader("X-Trace-Id");
        String userId = request.getHeader("X-User-Id");
        model.addAttribute("traceId", traceId);
        model.addAttribute("userId", userId);
        
        // 結構化日誌
        log.info("Request: {} {} | TraceId: {} | UA: {}", 
            request.getMethod(), request.getRequestURI(), traceId, 
            request.getHeader("User-Agent"));
    }
}

JSP 中獲取 (傳統專案)


<%-- header.jsp --%>
<%
    out.println("User-Agent: " + request.getHeader("User-Agent") + "
"); out.println("Referer: " + request.getHeader("Referer") + "
"); out.println("Accept-Language: " + request.getHeader("Accept-Language") + "
"); out.println("X-Forwarded-For: " + request.getHeader("X-Forwarded-For") + "
"); // 遍歷所有 Enumeration e = request.getHeaderNames(); while (e.hasMoreElements()) { String name = e.nextElement(); out.println(name + " = " + request.getHeader(name) + "
"); } %>

常見 Header 含義速查表

Header含義典型值應用場景
Host請求目標主機api.example.com:8080虛擬主機路由
User-Agent客戶端標識Mozilla/5.0..., PostmanRuntime/7.29瀏覽器兼容、爬蟲識別、統計
Referer來源頁面 URLhttps://google.com/search?q=java防盜鏈、來源統計、CSRF 檢查
Authorization認證憑證Bearer eyJhbGciOiJIUzI1NiJ9...OAuth2、JWT、Basic Auth
Cookie攜帶 CookieJSESSIONID=abc; token=xyz會話維持
Content-Type請求體媒體類型application/json; charset=UTF-8解析器選擇
Content-Length請求體長度1024限流、防洪
Accept可接受響應類型application/json, text/html內容協商
Accept-Encoding支援壓縮格式gzip, deflate, br響應壓縮
Accept-Language偏好語言zh-CN,zh;q=0.9,en;q=0.8國際化
X-Forwarded-For代理鏈路客戶端真實 IP203.0.113.195, 70.41.3.18獲取真實 IP 關鍵
X-Real-IPNginx 透傳真實 IP203.0.113.195獲取真實 IP
X-Request-Id / Trace-Id分布式追蹤 IDa1b2c3d4-e5f6-...鏈路追蹤、日誌關聯
If-None-Match / If-Modified-Since條件請求緩存驗證W/"abc123" / Wed, 21 Oct 2023304 Not Modified

獲取真實客戶端 IP 最佳實踐


public static String getRealIp(HttpServletRequest request) {
    // 1. 優先從代理 Header 獲取 (Nginx/網關配置透傳)
    String ip = request.getHeader("X-Forwarded-For");
    if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
        // 可能多級代理,取第一個非未知 IP
        return ip.split(",")[0].trim();
    }
    
    // 2. 備選 Header
    ip = request.getHeader("X-Real-IP");
    if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
        return ip;
    }
    
    // 3. 最後回退到 Servlet API
    return request.getRemoteAddr(); // 可能是代理 IP
}

前提:反向代理 (Nginx/網關) 必須正確設置:


# Nginx 配置
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;

Header 偽造風險與防範

風險攻擊示例防範措施
X-Forwarded-For 偽造攻擊者發送 `X-Forwarded-For: 1.2.3.4` 繞過 IP 白名單只信任**受信代理層**設置的 Header,應用層忽略客戶端直接發送的同名 Header
User-Agent 偽造爬蟲偽裝瀏覽器 UA結合行為分析、JS 挑戰、設備指紋,不單獨依賴 UA
Referer 偽造/隱藏防盜鏈繞過、隱私保護模式不將 Referer 作為唯一授權依據,配合 Token/簽名
自定義 Header 注入繞過內部服務間鑒權網關層清洗非白名單 Header,內部服務只信任網關注入的 Header

Spring Boot 2.6+ / Servlet 6.0 注意事項

  • 默認限制 Header 名稱字符範圍 (RFC 7230 token 規則),包含特殊字符的 Header 可能被拒絕。
  • 可通過 `server.max-http-header-size` 調整最大 Header 大小 (默認 8KB)。
  • Tomcat 10+ (Servlet 6) 更嚴格解析 Header 折行,舊客戶端可能不兼容。

總結

  1. 優先使用 @RequestHeader 聲明式綁定,類型安全、可選參數、文檖化友好。
  2. 需遍歷/動態獲取時注入 HttpServletRequest。
  3. 真實 IP 獲取**必須**配合反向代理正確透傳 `X-Forwarded-For`/`X-Real-IP`。
  4. 所有來自客戶端的 Header **不可信**,涉及安全決策時需經過網關清洗驗證。
  5. 分布式系統務必傳遞 `Trace-Id` 串聯全鏈路日誌。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved