想找java获取真实ip的源码。

James11 发布于 2013/09/04 14:35
阅读 4K+
收藏 8
在oschina看了几个人写的,试了一下感觉不是很对。想求一份亲测可用的源码。

以下是问题补充:

@James11:web程序 (2013/09/04 14:47)
加载中
2
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 );
}
王正航
王正航
回复 @低调的一只羊丶 : 楼上的代码是正确的,而你日志里面显示的192.168.2.1显示是个内网IP,是反向代理转发的,如果你想获取这个IP直接用request.getRemoteHost()就可以了,但是正生产环境下是没有意义的
James11
James11
我项目本身就是架设在vm虚拟机里面。还是没有得到 得到的是2013-09-05 11:52:54,284 [http-8080-2] [root] [INFO] - HOST:192.168.2.1 没有进if。。。
whaon
whaon
这不是csdn上的那个大大
0
thankjava
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();
}
}
}
}
0
James11
James11

引用来自“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地址的
0
萝卜权
萝卜权
request.getHeader("X-Real-IP");
request.getHeader("X-Forwarded-For");
request.getRemoteAddr()
0
伊万
伊万
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;
	}
James11
James11
这个 我已经试过了。
0
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;
James11
James11
Nginx 作为反向代理服务器 这个怎么理解,对部署方面不是很了解,不用nginx 就不能实现吗。
0
frankiegao123
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 而言其就是用户请求。
0
frankiegao123
frankiegao123

引用来自“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 地址的话,你必须要对部署的网络层次有所了解才行。
James11
James11
我得部署大概是这样得。 申请了域名 由oray花生壳解析到我的电脑的vm虚拟机上。
0
Qimat
Qimat
上面方法好像都是用的servlet容器获取,没有其它技术可以实现吗?
返回顶部
顶部