有没有办法获取连接到服务器的客户端的原始IP地址?
我可以使用request.getRemoteAddr()
,但我似乎总是得到代理或Web服务器的IP。
我想知道客户端用于连接到我的IP地址。有什么方法可以获取它吗?
有没有办法获取连接到服务器的客户端的原始IP地址?
我可以使用request.getRemoteAddr()
,但我似乎总是得到代理或Web服务器的IP。
我想知道客户端用于连接到我的IP地址。有什么方法可以获取它吗?
试试这个:
public static String getClientIpAddr(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
为何不使用更加优雅的解决方案,例如这种方式?
private static final List<String> IP_HEADERS = Arrays.asList("X-Forwarded-For", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR");
public static String getClientIpAddr(HttpServletRequest request) {
return IP_HEADERS.stream()
.map(request::getHeader)
.filter(Objects::nonNull)
.filter(ip -> !ip.isEmpty() && !ip.equalsIgnoreCase("unknown"))
.findFirst()
.orElseGet(request::getRemoteAddr);
}
代码去重!
request.getRemoteAddr()
是正确的方法。看起来您的代理更改了源IP。当一些代理这样做时,它们会在某个自定义HTTP头中添加原始IP。使用 request.getHeaderNames()
和 request.getHeaders(name)
并将所有内容打印出来,以查看是否有任何值得关注的内容,例如 X-CLIENT-IP
(我编的这一个,但它们看起来像这样)。
request.getRemoteAddr()
。public String getIpAddr(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
你不能以有意义的方式这样做。
代理服务器可能会添加代理头信息,但在许多情况下,这仍然是一个内部地址,对你来说是没有意义的。大多数在组织边缘的代理都配置为尽可能少地揭示网络内部的信息。
你打算用这些信息做什么?
如果使用代理或负载均衡器,“x-forwarded-for”请求头包含原始客户端IP。但我认为并非所有代理/负载均衡器都添加了此标头。
以下是一些Java代码以解析标头: http://www.codereye.com/2010/01/get-real-ip-from-request-in-java.html
如果不存在此标头,则应按照@Bozho的建议进行处理。
"String ipAddress = request.getHeader("x-forwarded-for");
if (ipAddress == null) {
ipAddress = request.getHeader("X_FORWARDED_FOR");
if (ipAddress == null){
ipAddress = request.getRemoteAddr();
}
}
为什么我认为我们应该首先从头部 'X-Forwarded-For
' 获取IP?如果你从 request.getRemoteAddr()
获取,它可能是客户端真实IP或转发请求的最后一个代理的IP。因此,我们无法确定它属于哪种情况。然而,如果 'X-Forwarded-For
' 设置到头部中,客户端IP将绑定到从中获取的最左边部分。
/**
* Try to get real ip from request:
* <ul>
* <li>try X-Forwarded-For</li>
* <li>try remote address</li>
* </ul>
*
* @param request request
* @return real ip or ""
*/
private String tryGetRealIp(HttpServletRequest request) {
// X-Forwarded-For: <client>, <proxy1>, <proxy2>
// If a request goes through multiple proxies, the IP addresses of each successive proxy is listed.
// This means, the right-most IP address is the IP address of the most recent proxy and
// the left-most IP address is the IP address of the originating client.
String forwards = request.getHeader("X-Forwarded-For");
if (StringUtils.isNotBlank(forwards)) {
// The left-most IP must be client ip
String ip = StringUtils.substringBefore(forwards, ",");
return ip;
} else if (StringUtils.isNotBlank(request.getRemoteAddr())) {
// this could be real client ip or last proxy ip which forwards the request
return request.getRemoteAddr();
}
return "";
}
request.getHeader("True-Client-IP")
它将返回客户端的IP地址