當系統部署於 Nginx、Squid 等反向代理後方,request.getRemoteAddr() 僅能取得代理伺服器 IP,無法直接獲得用戶真實 IP。
代理伺服器會在轉發請求時加入 X-Forwarded-For 標頭,格式為:client, proxy1, proxy2,第一個非 unknown 的 IP 即為真實客戶端。
public String getRemoteIP(HttpServletRequest req) {
String ip = req.getHeader("x-forwarded-for");
return (ip == null) ? req.getRemoteAddr() : ip;
}
public String getRealIP(HttpServletRequest req) {
String ip = req.getHeader("x-forwarded-for");
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = req.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = req.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = req.getRemoteAddr();
}
// 多層代理取第一個有效 IP
if (ip != null && ip.contains(",")) {
for (String part : ip.split(",")) {
part = part.trim();
if (!"unknown".equalsIgnoreCase(part)) return part;
}
}
return ip;
}
forwarded_for off 會導致 X-Forwarded-For: unknown,需檢查代理設定。