9
回答
想找java获取真实ip的源码。
在oschina看了几个人写的,试了一下感觉不是很对。想求一份亲测可用的源码。
举报
James11
发帖于5年前 9回/4K+阅

以下是问题补充:

共有9个答案 最后回答: 5年前

一般的话,在 Servlet 中会先从 HTTP 请求头中获取,这是因为 Servlet 容器并不一定是真正暴露在 Internet 上的,而是通过 Web 服务器,甚至是负载均衡设备之后的,一个客户端的请求过来,经过了好几次的反向代理,如果直接使用 HttpServletRequest 的 getRemoteAddr() 获取的将是位于 Servlet 上一层代理服务器的 IP 地址,因此这种方式在生产环境中是不可靠的。

一般通过反向代理服务器的客户端请求,代理服务器都会将客户端源 IP 地址附加在原始的 HTTP 请求头上,非标准协议的代理源 IP 地址请求头有 X-Forwarded-For、X-Real-Ip 等,可以直接依据优先级从这些 HTTP 头获取数据,如果实现在获取不到的话,再从 HttpServletRequest 的 getRemoteAddr() 方法中获取。

参考代码如下:

/**
 * <p>
 * Web 服务器反向代理中用于存放客户端原始 IP 地址的 Http header 名字,
 * 若新增其他的需要增加或者修改其中的值。
 * </p>
 */
private static final String[] PROXY_REMOTE_IP_ADDRESS = { "X-Forwarded-For", "X-Real-IP" };


/**
 * <p>
 * 获取请求的客户端的 IP 地址。若应用服务器前端配有反向代理的 Web 服务器,
 * 需要在 Web 服务器中将客户端原始请求的 IP 地址加入到 HTTP header 中。
 * 详见 {@link #PROXY_REMOTE_IP_ADDRESS}
 * </p>
 */
public static String getRemoteIp( HttpServletRequest request ) {
    for ( int i = 0 ; i < PROXY_REMOTE_IP_ADDRESS.length ; i++ ) {
        String ip = request.getHeader( PROXY_REMOTE_IP_ADDRESS[i] );
        if ( ip != null && ip.trim().length > 0 ) {
            return getRemoteIpFromForward( ip.trim() );
        }
    }
    return request.getRemoteHost();
}

/**
 * <p>
 * 从 HTTP Header 中截取客户端连接 IP 地址。如果经过多次反向代理,
 * 在请求头中获得的是以“,&lt;SP&gt;”分隔 IP 地址链,第一段为客户端 IP 地址。
 * </p>
 *
 * @param xforwardIp 从 HTTP 请求头中获取转发过来的 IP 地址链
 * @return 客户端源 IP 地址
 */
private static String getRemoteIpFromForward( String xforwardIp ) {
    int commaOffset = xforwardIp.indexOf( ',' );
    if ( commaOffset < 0 ) {
        return xforwardIp;
    }
    return xforwardIp.substring( 0 , commaOffset );
}
--- 共有 3 条评论 ---
王正航回复 @低调的一只羊丶 : 楼上的代码是正确的,而你日志里面显示的192.168.2.1显示是个内网IP,是反向代理转发的,如果你想获取这个IP直接用request.getRemoteHost()就可以了,但是正生产环境下是没有意义的 5年前 回复
James11我项目本身就是架设在vm虚拟机里面。还是没有得到 得到的是2013-09-05 11:52:54,284 [http-8080-2] [root] [INFO] - HOST:192.168.2.1 没有进if。。。 5年前 回复
whaon这不是csdn上的那个大大 5年前 回复


import java.io.IOException;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;




public class NetworkTest {


public static void main(String[] args) {
try {
/*
* 获取主机列表接口
*/
Enumeration<NetworkInterface> networkList = NetworkInterface.getNetworkInterfaces();
if(networkList == null){
System.out.println("没有找到相关信息");
}else{
while(networkList.hasMoreElements()){
NetworkInterface networkItf = networkList.nextElement();
System.out.println(networkItf.getName());
Enumeration<InetAddress> addressList = networkItf.getInetAddresses();
if(!addressList.hasMoreElements()){
System.out.println("\t该NetworkInterface没有InetAddress相关信息");
}else{
while (addressList.hasMoreElements()) {
InetAddress inetAddress = (InetAddress) addressList.nextElement();
System.out.println("\t" + (inetAddress instanceof Inet4Address ? "IP4类型" : (inetAddress instanceof Inet6Address ? "IP6类型" : "未知IP4或IP6")));
System.out.println("\thostAddr:" + inetAddress.getHostAddress() + " hostName:" + inetAddress.getHostName());
}
}
}
}
} catch (SocketException e) {
e.printStackTrace();
}
for (String host : args) {
try {
InetAddress[] inetAddressList = InetAddress.getAllByName(host);
for (InetAddress inetAddress : inetAddressList) {
System.out.println("IP:" + inetAddress.getHostAddress());
System.out.println("\t主机名为:" + inetAddress.getHostName());
System.out.println("\t局域地址:" + inetAddress.isSiteLocalAddress());
System.out.println("\t组播地址:" + inetAddress.isMulticastAddress());
System.out.println("\t发送3秒数据包是否能与该IP进行数据报文交互:" + inetAddress.isReachable(3000));
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

引用来自“thankjava”的答案



import java.io.IOException;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;




public class NetworkTest {


public static void main(String[] args) {
try {
/*
* 获取主机列表接口
*/
Enumeration<NetworkInterface> networkList = NetworkInterface.getNetworkInterfaces();
if(networkList == null){
System.out.println("没有找到相关信息");
}else{
while(networkList.hasMoreElements()){
NetworkInterface networkItf = networkList.nextElement();
System.out.println(networkItf.getName());
Enumeration<InetAddress> addressList = networkItf.getInetAddresses();
if(!addressList.hasMoreElements()){
System.out.println("\t该NetworkInterface没有InetAddress相关信息");
}else{
while (addressList.hasMoreElements()) {
InetAddress inetAddress = (InetAddress) addressList.nextElement();
System.out.println("\t" + (inetAddress instanceof Inet4Address ? "IP4类型" : (inetAddress instanceof Inet6Address ? "IP6类型" : "未知IP4或IP6")));
System.out.println("\thostAddr:" + inetAddress.getHostAddress() + " hostName:" + inetAddress.getHostName());
}
}
}
}
} catch (SocketException e) {
e.printStackTrace();
}
for (String host : args) {
try {
InetAddress[] inetAddressList = InetAddress.getAllByName(host);
for (InetAddress inetAddress : inetAddressList) {
System.out.println("IP:" + inetAddress.getHostAddress());
System.out.println("\t主机名为:" + inetAddress.getHostName());
System.out.println("\t局域地址:" + inetAddress.isSiteLocalAddress());
System.out.println("\t组播地址:" + inetAddress.isMulticastAddress());
System.out.println("\t发送3秒数据包是否能与该IP进行数据报文交互:" + inetAddress.isReachable(3000));
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
谢谢啊。请问一下有没有web程序获取ip地址的
public static String getIpAddr(HttpServletRequest request)
	{
		String ip = request.getHeader("X-REAL-IP");
		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;
	}
--- 共有 1 条评论 ---
James11这个 我已经试过了。 5年前 回复

引用来自“frankiegao123”的答案

一般的话,在 Servlet 中会先从 HTTP 请求头中获取,这是因为 Servlet 容器并不一定是真正暴露在 Internet 上的,而是通过 Web 服务器,甚至是负载均衡设备之后的,一个客户端的请求过来,经过了好几次的反向代理,如果直接使用 HttpServletRequest 的 getRemoteAddr() 获取的将是位于 Servlet 上一层代理服务器的 IP 地址,因此这种方式在生产环境中是不可靠的。

一般通过反向代理服务器的客户端请求,代理服务器都会将客户端源 IP 地址附加在原始的 HTTP 请求头上,非标准协议的代理源 IP 地址请求头有 X-Forwarded-For、X-Real-Ip 等,可以直接依据优先级从这些 HTTP 头获取数据,如果实现在获取不到的话,再从 HttpServletRequest 的 getRemoteAddr() 方法中获取。

参考代码如下:

/**
 * <p>
 * Web 服务器反向代理中用于存放客户端原始 IP 地址的 Http header 名字,
 * 若新增其他的需要增加或者修改其中的值。
 * </p>
 */
private static final String[] PROXY_REMOTE_IP_ADDRESS = { "X-Forwarded-For", "X-Real-IP" };


/**
 * <p>
 * 获取请求的客户端的 IP 地址。若应用服务器前端配有反向代理的 Web 服务器,
 * 需要在 Web 服务器中将客户端原始请求的 IP 地址加入到 HTTP header 中。
 * 详见 {@link #PROXY_REMOTE_IP_ADDRESS}
 * </p>
 */
public static String getRemoteIp( HttpServletRequest request ) {
    for ( int i = 0 ; i < PROXY_REMOTE_IP_ADDRESS.length ; i++ ) {
        String ip = request.getHeader( PROXY_REMOTE_IP_ADDRESS[i] );
        if ( ip != null && ip.trim().length > 0 ) {
            return getRemoteIpFromForward( ip.trim() );
        }
    }
    return request.getRemoteHost();
}

/**
 * <p>
 * 从 HTTP Header 中截取客户端连接 IP 地址。如果经过多次反向代理,
 * 在请求头中获得的是以“,&lt;SP&gt;”分隔 IP 地址链,第一段为客户端 IP 地址。
 * </p>
 *
 * @param xforwardIp 从 HTTP 请求头中获取转发过来的 IP 地址链
 * @return 客户端源 IP 地址
 */
private static String getRemoteIpFromForward( String xforwardIp ) {
    int commaOffset = xforwardIp.indexOf( ',' );
    if ( commaOffset < 0 ) {
        return xforwardIp;
    }
    return xforwardIp.substring( 0 , commaOffset );
}
回复 @低调的一只羊丶 : 你没有仔细看我的回复哦。请求如果通过反向代理服务器的话,那需要在代理服务器上将原始请求客户端的 IP 地址放到自定义的 HTTP 头中去的,并不是什么事情都不做就可以获取得到的!

比如在 Nginx 作为反向代理服务器处理用户过来 HTTP 请求并将请求转发给后端的 Tomcat 或者其他什么应用服务器的话,那 Nginx 就需要这样设置一下的:

proxy_set_header  X-Real-IP  $remote_addr;
--- 共有 1 条评论 ---
James11Nginx 作为反向代理服务器 这个怎么理解,对部署方面不是很了解,不用nginx 就不能实现吗。 5年前 回复

引用来自“frankiegao123”的答案

引用来自“frankiegao123”的答案

一般的话,在 Servlet 中会先从 HTTP 请求头中获取,这是因为 Servlet 容器并不一定是真正暴露在 Internet 上的,而是通过 Web 服务器,甚至是负载均衡设备之后的,一个客户端的请求过来,经过了好几次的反向代理,如果直接使用 HttpServletRequest 的 getRemoteAddr() 获取的将是位于 Servlet 上一层代理服务器的 IP 地址,因此这种方式在生产环境中是不可靠的。

一般通过反向代理服务器的客户端请求,代理服务器都会将客户端源 IP 地址附加在原始的 HTTP 请求头上,非标准协议的代理源 IP 地址请求头有 X-Forwarded-For、X-Real-Ip 等,可以直接依据优先级从这些 HTTP 头获取数据,如果实现在获取不到的话,再从 HttpServletRequest 的 getRemoteAddr() 方法中获取。

参考代码如下:

/**
 * <p>
 * Web 服务器反向代理中用于存放客户端原始 IP 地址的 Http header 名字,
 * 若新增其他的需要增加或者修改其中的值。
 * </p>
 */
private static final String[] PROXY_REMOTE_IP_ADDRESS = { "X-Forwarded-For", "X-Real-IP" };


/**
 * <p>
 * 获取请求的客户端的 IP 地址。若应用服务器前端配有反向代理的 Web 服务器,
 * 需要在 Web 服务器中将客户端原始请求的 IP 地址加入到 HTTP header 中。
 * 详见 {@link #PROXY_REMOTE_IP_ADDRESS}
 * </p>
 */
public static String getRemoteIp( HttpServletRequest request ) {
    for ( int i = 0 ; i < PROXY_REMOTE_IP_ADDRESS.length ; i++ ) {
        String ip = request.getHeader( PROXY_REMOTE_IP_ADDRESS[i] );
        if ( ip != null && ip.trim().length > 0 ) {
            return getRemoteIpFromForward( ip.trim() );
        }
    }
    return request.getRemoteHost();
}

/**
 * <p>
 * 从 HTTP Header 中截取客户端连接 IP 地址。如果经过多次反向代理,
 * 在请求头中获得的是以“,&lt;SP&gt;”分隔 IP 地址链,第一段为客户端 IP 地址。
 * </p>
 *
 * @param xforwardIp 从 HTTP 请求头中获取转发过来的 IP 地址链
 * @return 客户端源 IP 地址
 */
private static String getRemoteIpFromForward( String xforwardIp ) {
    int commaOffset = xforwardIp.indexOf( ',' );
    if ( commaOffset < 0 ) {
        return xforwardIp;
    }
    return xforwardIp.substring( 0 , commaOffset );
}
回复 @低调的一只羊丶 : 你没有仔细看我的回复哦。请求如果通过反向代理服务器的话,那需要在代理服务器上将原始请求客户端的 IP 地址放到自定义的 HTTP 头中去的,并不是什么事情都不做就可以获取得到的!

比如在 Nginx 作为反向代理服务器处理用户过来 HTTP 请求并将请求转发给后端的 Tomcat 或者其他什么应用服务器的话,那 Nginx 就需要这样设置一下的:

proxy_set_header  X-Real-IP  $remote_addr;
回复 @低调的一只羊丶 : 如果用户请求的域名 DNS 解析是在一个 Tomcat 服务器上的,那么就可以使用 getRemoteAddr 获取用户请求客户端的 IP 地址。但实际情况下,用户的一个请求,最终到你的 Tomcat 服务器上,其间可能经历了多重代理服务器的转发,如果是这样的话,那么使用 getRemoteAddr 获取的是 Tomcat 上一层代理服务器的 IP 地址,因为请求是由这个服务器转发过来的,对于 Tomcat 而言其就是用户请求。

引用来自“frankiegao123”的答案

引用来自“frankiegao123”的答案

引用来自“frankiegao123”的答案

一般的话,在 Servlet 中会先从 HTTP 请求头中获取,这是因为 Servlet 容器并不一定是真正暴露在 Internet 上的,而是通过 Web 服务器,甚至是负载均衡设备之后的,一个客户端的请求过来,经过了好几次的反向代理,如果直接使用 HttpServletRequest 的 getRemoteAddr() 获取的将是位于 Servlet 上一层代理服务器的 IP 地址,因此这种方式在生产环境中是不可靠的。

一般通过反向代理服务器的客户端请求,代理服务器都会将客户端源 IP 地址附加在原始的 HTTP 请求头上,非标准协议的代理源 IP 地址请求头有 X-Forwarded-For、X-Real-Ip 等,可以直接依据优先级从这些 HTTP 头获取数据,如果实现在获取不到的话,再从 HttpServletRequest 的 getRemoteAddr() 方法中获取。

参考代码如下:

/**
 * <p>
 * Web 服务器反向代理中用于存放客户端原始 IP 地址的 Http header 名字,
 * 若新增其他的需要增加或者修改其中的值。
 * </p>
 */
private static final String[] PROXY_REMOTE_IP_ADDRESS = { "X-Forwarded-For", "X-Real-IP" };


/**
 * <p>
 * 获取请求的客户端的 IP 地址。若应用服务器前端配有反向代理的 Web 服务器,
 * 需要在 Web 服务器中将客户端原始请求的 IP 地址加入到 HTTP header 中。
 * 详见 {@link #PROXY_REMOTE_IP_ADDRESS}
 * </p>
 */
public static String getRemoteIp( HttpServletRequest request ) {
    for ( int i = 0 ; i < PROXY_REMOTE_IP_ADDRESS.length ; i++ ) {
        String ip = request.getHeader( PROXY_REMOTE_IP_ADDRESS[i] );
        if ( ip != null && ip.trim().length > 0 ) {
            return getRemoteIpFromForward( ip.trim() );
        }
    }
    return request.getRemoteHost();
}

/**
 * <p>
 * 从 HTTP Header 中截取客户端连接 IP 地址。如果经过多次反向代理,
 * 在请求头中获得的是以“,&lt;SP&gt;”分隔 IP 地址链,第一段为客户端 IP 地址。
 * </p>
 *
 * @param xforwardIp 从 HTTP 请求头中获取转发过来的 IP 地址链
 * @return 客户端源 IP 地址
 */
private static String getRemoteIpFromForward( String xforwardIp ) {
    int commaOffset = xforwardIp.indexOf( ',' );
    if ( commaOffset < 0 ) {
        return xforwardIp;
    }
    return xforwardIp.substring( 0 , commaOffset );
}
回复 @低调的一只羊丶 : 你没有仔细看我的回复哦。请求如果通过反向代理服务器的话,那需要在代理服务器上将原始请求客户端的 IP 地址放到自定义的 HTTP 头中去的,并不是什么事情都不做就可以获取得到的!

比如在 Nginx 作为反向代理服务器处理用户过来 HTTP 请求并将请求转发给后端的 Tomcat 或者其他什么应用服务器的话,那 Nginx 就需要这样设置一下的:

proxy_set_header  X-Real-IP  $remote_addr;
回复 @低调的一只羊丶 : 如果用户请求的域名 DNS 解析是在一个 Tomcat 服务器上的,那么就可以使用 getRemoteAddr 获取用户请求客户端的 IP 地址。但实际情况下,用户的一个请求,最终到你的 Tomcat 服务器上,其间可能经历了多重代理服务器的转发,如果是这样的话,那么使用 getRemoteAddr 获取的是 Tomcat 上一层代理服务器的 IP 地址,因为请求是由这个服务器转发过来的,对于 Tomcat 而言其就是用户请求。
如果你需要获取用户请求实际的 IP 地址的话,你必须要对部署的网络层次有所了解才行。
--- 共有 1 条评论 ---
James11我得部署大概是这样得。 申请了域名 由oray花生壳解析到我的电脑的vm虚拟机上。 5年前 回复
顶部