Java获取客户端IP
来源:互联网 发布:淘宝会员等级会降低吗 编辑:程序博客网 时间:2024/06/08 00:15
转载地址:Java获取客户端IP
这里虽然是转载的博文,在看博文之前先说明一下,如果你使用的是公司的内网访问,那么对外的出口可能只有一个或者几个,那么客户端的IP就有可能两个人获取的同样的IP!
在开发工作中,我们常常需要获取客户端的IP。一般获取客户端的IP地址的方法是:request.getRemoteAddr();但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实IP地址了。
原因:由于在客户端和服务之间增加了中间代理,因此服务器无法直接拿到客户端的IP,服务器端应用也无法直接通过转发请求的地址返回给客户端。
现在图示代理上网和IP的关系:
第二种情况:通过代理服务器如:Nginx,Squid等一层代理或多层代理上网,如下图:
需要注意的是X-Forwarded-For和X-Real-IP都不是http的正式协议头,而是squid等反向代理软件最早引入的,之所以resin能拿到,是因为NGINX里一般缺省都会这么配置转发的http请求:
location / { proxy_pass http://yourdomain.com; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
从X-Forwarded-For的定义来看,ips[0]才是原始客户端ip,如果这个都不是,那拿第二个就更不靠谱了,我们平时检验的时候,可能是直接在内网挂代理去访问的,跟外面网友访问经过的网络路径不一样,后面不停添加的是经过的每一层代理ip才对,下面举例说明;
request.getRemoteAddr() 192.168.239.196
request.getHeader(“X-Forwarded-For”) 58.63.227.162, 192.168.237.178, 192.168.238.218
request.getHeader(“X-Real-IP”) 192.168.238.218
所以访问的流程应该是这样,客户端58.63.227.162发出请求,经过192.168.237.178, 192.168.238.218两层转发,到了192.168.239.196这台NGINX上,NGINX就把X-Real-IP头设成了自己看到的remote_addr,也就是直接发给到他的192.168.238.218,这时候resin收到这个包,对resin来说直接发给他的remote_addr就是NGINX的ip,也就是192.168.239.196,那么resin里面的request.getRemoteAddr()就是192.168.239.196,那么在resin里拿最原始的ip逻辑(也就是拿能够知道的最外层的ip)应该是这样:
如果XFF不为空,拿XFF的左边第一个 如果XFF为空,拿XRI 如果XRI为空,只能拿request.getRemoteAddr(),也就是只能拿到最直接发给他的机器ip了,
其他都不可考究,参考代码如下:
第一种代码:
/** * 从Request对象中获得客户端IP,处理了HTTP代理服务器和Nginx的反向代理截取了ip * @param request * @return ip */ public static String getLocalIp(HttpServletRequest request) { String remoteAddr = request.getRemoteAddr(); String forwarded = request.getHeader("X-Forwarded-For"); String realIp = request.getHeader("X-Real-IP"); String ip = null; if (realIp == null) { if (forwarded == null) { ip = remoteAddr; } else { ip = remoteAddr + "/" + forwarded.split(",")[0]; } } else { if (realIp.equals(forwarded)) { ip = realIp; } else { if(forwarded != null){ forwarded = forwarded.split(",")[0]; } ip = realIp + "/" + forwarded; } } return ip; }
第二种代码:
public static String getIp(HttpServletRequest request) { String remoteAddr = request.getRemoteAddr(); String forwarded = request.getHeader("X-Forwarded-For"); String realIp = request.getHeader("X-Real-IP"); String ip = null; if (realIp == null) { if (forwarded == null) { ip = remoteAddr; } else { ip = remoteAddr + "/" + forwarded; } } else { if (realIp.equals(forwarded)) { ip = realIp; } else { ip = realIp + "/" + forwarded.replaceAll(", " + realIp, ""); } } return ip; }
第三种代码:
public static String getIp2(HttpServletRequest request) { String ip = request.getHeader("X-Forwarded-For"); if(StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)){ //多次反向代理后会有多个ip值,第一个ip才是真实ip int index = ip.indexOf(","); if(index != -1){ return ip.substring(0,index); }else{ return ip; } } ip = request.getHeader("X-Real-IP"); if(StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)){ return ip; } return request.getRemoteAddr(); }
第三种是最合适的,最清晰理解的!
附两个方法:也是从其他地方看到的,记录下来,方便以后学习!
/** * 通过HttpServletRequest返回IP地址 * @param request HttpServletRequest * @return ip String * @throws Exception */public String getIpAddr(HttpServletRequest request) throws Exception { 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;} /** * 通过IP地址获取MAC地址 * @param ip String,127.0.0.1格式 * @return mac String * @throws Exception */public String getMACAddress(String ip) throws Exception { String line = ""; String macAddress = ""; final String MAC_ADDRESS_PREFIX = "MAC Address = "; final String LOOPBACK_ADDRESS = "127.0.0.1"; //如果为127.0.0.1,则获取本地MAC地址。 if (LOOPBACK_ADDRESS.equals(ip)) { InetAddress inetAddress = InetAddress.getLocalHost(); //貌似此方法需要JDK1.6。 byte[] mac = NetworkInterface.getByInetAddress(inetAddress).getHardwareAddress(); //下面代码是把mac地址拼装成String StringBuilder sb = new StringBuilder(); for (int i = 0; i < mac.length; i++) { if (i != 0) { sb.append("-"); } //mac[i] & 0xFF 是为了把byte转化为正整数 String s = Integer.toHexString(mac[i] & 0xFF); sb.append(s.length() == 1 ? 0 + s : s); } //把字符串所有小写字母改为大写成为正规的mac地址并返回 macAddress = sb.toString().trim().toUpperCase(); return macAddress; } //获取非本地IP的MAC地址 try { Process p = Runtime.getRuntime().exec("nbtstat -A " + ip); InputStreamReader isr = new InputStreamReader(p.getInputStream()); BufferedReader br = new BufferedReader(isr); while ((line = br.readLine()) != null) { if (line != null) { int index = line.indexOf(MAC_ADDRESS_PREFIX); if (index != -1) { macAddress = line.substring(index + MAC_ADDRESS_PREFIX.length()).trim().toUpperCase(); } } } br.close(); } catch (IOException e) { e.printStackTrace(System.out); } return macAddress;}
- java获取客户端ip
- JAVA 获取客户端 IP
- java获取客户端ip
- JAVA 获取客户端IP
- java获取客户端IP
- JAVA获取客户端IP
- java获取客户端Ip
- JAVA获取客户端IP
- Java获取客户端IP
- Java获取客户端IP
- Java获取客户端IP
- Java获取客户端IP
- Java获取客户端IP
- Java获取客户端IP
- java 获取客户端ip
- Java获取客户端IP
- Java获取客户端IP
- Java获取客户端IP
- POJ1050 To the Max【最大子串和】
- iOS 单元测试4- 单元测试编码规范
- 图片上传出现的问题
- 遍历删除文件
- iOS-设置导航栏颜色(iOS8+)
- Java获取客户端IP
- CodeForces 633E Startup Funding (概率)
- AAPT err(Facade for): libpng error: Not a PNG file 错误解决
- Android -- 设置textview文字居中或者控件居中
- java md5加密
- Count Primes - Javascript
- 指向学生类的指针
- 关于artTemplate使用的一点小心得
- 程序员心想事成的 10 步技巧