Servlets 如何在servlet中获取客户端的远程地址?

Servlets 如何在servlet中获取客户端的远程地址?,servlets,proxy,client,ip-address,Servlets,Proxy,Client,Ip Address,有没有什么方法可以让我得到客户端到服务器的原始IP地址? 我可以使用request.getRemoteAddr(),但我似乎总是能够获得代理或web服务器的IP 我想知道客户端用来连接我的IP地址。还有什么我可以得到的吗?请求。getRemoteAddr()就是方法。您的代理似乎更改了源IP。当某些代理这样做时,它们会将原始IP添加到某个自定义http头中。使用request.getHeaderNames()和request.getHeaders(name)并打印所有文件,以查看是否没有任何感兴

有没有什么方法可以让我得到客户端到服务器的原始IP地址? 我可以使用
request.getRemoteAddr()
,但我似乎总是能够获得代理或web服务器的IP


我想知道客户端用来连接我的IP地址。还有什么我可以得到的吗?

请求。getRemoteAddr()就是方法。您的代理似乎更改了源IP。当某些代理这样做时,它们会将原始IP添加到某个自定义http头中。使用
request.getHeaderNames()
request.getHeaders(name)
并打印所有文件,以查看是否没有任何感兴趣的内容。像
X-CLIENT-IP
(这个是虚构的,但看起来像这样)

你不能用一种有意义的方式来做这件事

代理可能会也可能不会添加代理for头,但在许多情况下,这将是一个仅限内部的地址,因此对您来说毫无意义。组织边缘的大多数代理配置为尽可能少地揭示网络的内部情况

您打算将此信息用于什么目的

试试这个:

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;  
    }  
如果使用代理或负载平衡器,“x-forwarded-for”请求标头包含原始客户端IP。但我认为并非所有代理/lb都会添加此标题

下面是一些解析标头的java代码:


如果这个标题不存在,那么我将按照@Bozho所建议的方法进行操作

这是我使用过的最好的解决方案

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;      
} 

由于这通常是一个部署问题,而不是应用程序问题,因此另一种方法是适当地配置应用程序容器。配置后,容器将负责检查相应的头,应用程序将继续使用
request.getRemoteAddr()

例如,在Tomcat中,可以使用。我假设大多数应用服务器都有类似的功能


容器还可以了解前端负载平衡器是否正在终止SSL连接,并通过HTTP将请求转发到应用服务器。当应用程序需要生成指向自身的URL时,这一点很重要。

为什么不使用这样一个更优雅的解决方案呢

InetAddress inetAddress = InetAddress.getLocalHost();
String ip = inetAddress.getHostAddress();
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);
}
private static final List IP_HEADERS=Arrays.asList(“X-Forwarded-For”、“代理客户端IP”、“WL代理客户端IP”、“HTTP_客户端IP”、“HTTP_-Forwarded_For”);
公共静态字符串GetClientIPDR(HttpServletRequest){
返回IP_头文件。stream()
.map(请求::getHeader)
.filter(对象::非空)
.filter(ip->!ip.isEmpty()&&!ip.equalsIgnoreCase(“未知”))
.findFirst()
.orElseGet(请求::getRemoteAddr);
}

重复删除你的代码

为什么我认为我们应该首先从标题“
X-Forwarded-For
”获取IP?如果从
request.getRemoteAddr()
获取,则可能是。因此,我们无法判断它属于哪种情况。但是,如果在标头中设置了,则客户端ip将是您从中获得的最左侧部分

/**
*尝试从请求中获取真正的ip:
*
    *
  • 尝试X-Forwarded-For
  • *
  • 尝试远程地址
  • *
* *@param请求 *@返回真实ip或“” */ 私有字符串tryGetRealIp(HttpServletRequest请求){ //X-For:, //如果请求通过多个代理,则会列出每个后续代理的IP地址。 //这意味着,最右边的IP地址是最新代理服务器和服务器的IP地址 //最左边的IP地址是发起客户端的IP地址。 字符串转发=request.getHeader(“X-Forwarded-For”); if(StringUtils.isNotBlank(forwards)){ //最左边的IP必须是客户端IP 字符串ip=StringUtils.substringBefore(forwards,“,”); 返回ip; }else if(StringUtils.isNotBlank(request.getRemoteAddr())){ //这可能是转发请求的真实客户端ip或最后一个代理ip 返回请求。getRemoteAddr(); } 返回“”; }
request.getHeader(“真正的客户端IP”)


它将返回客户端IP地址

嗯,我需要记录正在访问的用户的地址。你是对的,有些代理似乎删除了它,我经常让代理替换它。。。。我在想,如果我可以从SSL会话库中获得一些信息,我将检查标题。。。。例如,当它通过web服务器时,我会得到web服务器的地址。你是说request.getHeaderNames()吗?在这种情况下,可以吗,使用if conditiona而不是if/else?是,因为我们需要检查上一个操作是否成功,也许使用do-while会更好,因为X-Forwarded可以包含多个IP地址。这只是提供本地主机的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);
}