转自:

http://www.cnblogs.com/icerainsoft/p/3584532.html

http://www.cnblogs.com/bingya/articles/3134227.html

在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr() ,这种方法在大部分情况下都是有效的。但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实IP地址了。

果使用了反向代理软件,将http://192.168.1.110:2046/ 的URL反向代理为http://www.xxx.com/
的URL时,用request.getRemoteAddr() 方法获取的IP地址是:127.0.0.1 或 192.168.1.110
,而并不是客户端的真实IP。
经过代理以后,由于在客户端和服务之间增加了中间层,因此服务器无法直接拿到客户端的IP,服务器端应用也无法直接
通过转发请求的地址返回给客户端。但是在转发请求的HTTP头信息中,增加了X-FORWARDED-FOR信息。用以跟踪原有的客户端IP地址和原来客
户端请求的服务器地址。当我们访问http://www.xxx.com/index.jsp/
时,其实并不是我们浏览器真正访问到了服务器上的index.jsp文件,而是先由代理服务器去访问http://192.168.1.110:2046
/index.jsp
,代理服务器再将访问到的结果返回给我们的浏览器,因为是代理服务器去访问index.jsp的,所以index.jsp中通过
request.getRemoteAddr() 的方法获取的IP实际上是代理服务器的地址,并不是客户端的IP地址。
于是可得出获得客户端真实IP地址的方法一:

  1. public String getRemortIP(HttpServletRequest request) {
  2. if (request.getHeader("x-forwarded-for") == null) {
  3. return request.getRemoteAddr();
  4. }
  5. return request.getHeader("x-forwarded-for");
  6. }

可是当我访问http://www.xxx.com/index.jsp/ 时,返回的IP地址始终是unknown,也并不是如上所示的127.0.0.1 或 192.168.1.110 了,而我访问http://192.168.1.110:2046/index.jsp 时,则能返回客户端的真实IP地址,写了个方法去验证。原因出在了Squid上。squid.conf 的配制文件 forwarded_for 项默认是为on,如果 forwarded_for 设成了 off  则:X-Forwarded-For: unknown
于是可得出获得客户端真实IP地址的方法二:

  1. public String getRemoteHost(javax.servlet.http.HttpServletRequest request){
  2. String ip = request.getHeader("x-forwarded-for");
  3. if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
  4. ip = request.getHeader("Proxy-Client-IP");
  5. }
  6. if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
  7. ip = request.getHeader("WL-Proxy-Client-IP");
  8. }
  9. if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
  10. ip = request.getRemoteAddr();
  11. }
  12. return ip.equals("0:0:0:0:0:0:0:1")?"127.0.0.1":ip;
  13. }

如果是Netty4.x

  1. public String getRemoteIP(FullHttpRequest httpRequest) {
  2. String ip = "";
  3. try{
  4. String ipForwarded = httpRequest.headers().get("x-forwarded-for");
  5. if (StringUtils.isBlank(ipForwarded) || "unknown".equalsIgnoreCase(ipForwarded)) {
  6. InetSocketAddress insocket = (InetSocketAddress)channel.remoteAddress();
  7. ip = insocket.getAddress().getHostAddress();
  8. } else {
  9. ip = ipForwarded;
  10. }
  11. }catch(Exception e){
  12. logger.error("getRemoteIP(): get remote ip fail!", e);
  13. }
  14. if("0:0:0:0:0:0:0:1".equals(ip)){
  15. ip = "127.0.0.1";
  16. }
  17. return ip;
  18. }

如果通过了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP值,究竟哪个才是真正的用户端的真实IP呢?
 答案是取X-Forwarded-For中第一个非unknown的有效IP字符串。如:
    X-Forwarded-For:192.168.1.110, 192.168.1.120, 192.168.1.130, 192.168.1.100
    用户真实IP为: 192.168.1.110

  1. package com.ctrip.cep.mockserver.util;
  2.  
  3. import org.slf4j.Logger;
  4. import org.slf4j.LoggerFactory;
  5.  
  6. import javax.servlet.http.HttpServletRequest;
  7. import java.io.IOException;
  8.  
  9. /**
  10. * Created by lzyan on 2017/7/11.
  11. */
  12. public final class NetworkUtil {
  13. private static Logger logger = LoggerFactory.getLogger(NetworkUtil.class);
  14.  
  15. /**
  16. * 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址
  17. *
  18. * @param request
  19. * @return
  20. * @throws IOException
  21. */
  22. public final static String getIpAddress(HttpServletRequest request) {
  23. // 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址
  24.  
  25. String ip = request.getHeader("X-Forwarded-For");
  26. // logger.debug("getIpAddress(HttpServletRequest) - X-Forwarded-For - String ip=" + ip);
  27.  
  28. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  29. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  30. ip = request.getHeader("Proxy-Client-IP");
  31. // logger.debug("getIpAddress(HttpServletRequest) - Proxy-Client-IP - String ip=" + ip);
  32. }
  33. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  34. ip = request.getHeader("WL-Proxy-Client-IP");
  35. // logger.debug("getIpAddress(HttpServletRequest) - WL-Proxy-Client-IP - String ip=" + ip);
  36. }
  37. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  38. ip = request.getHeader("HTTP_CLIENT_IP");
  39. // logger.debug("getIpAddress(HttpServletRequest) - HTTP_CLIENT_IP - String ip=" + ip);
  40. }
  41. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  42. ip = request.getHeader("HTTP_X_FORWARDED_FOR");
  43. // logger.debug("getIpAddress(HttpServletRequest) - HTTP_X_FORWARDED_FOR - String ip=" + ip);
  44. }
  45. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  46. ip = request.getRemoteAddr();
  47. // logger.debug("getIpAddress(HttpServletRequest) - getRemoteAddr - String ip=" + ip);
  48. }
  49. } else if (ip.length() > 15) {
  50. String[] ips = ip.split(",");
  51. for (int index = 0; index < ips.length; index++) {
  52. String strIp = ips[index];
  53. if (!("unknown".equalsIgnoreCase(strIp))) {
  54. ip = strIp;
  55. break;
  56. }
  57. }
  58. }
  59. return ip;
  60. }
  61.  
  62. }

根据Request获取客户端IP的更多相关文章

  1. 根据Request获取客户端IP 内网IP及外网IP

    在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr() ,这种方法在大部分情况下都是有效的.但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实 ...

  2. Request获取客户端IP

    获取客户端的IP地址的方法是:request.getRemoteAddr() ,这种方法在大部分情况下都是有效的.但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实IP地址了. ...

  3. C#服务器获取客户端IP地址以及归属地探秘

    背景:博主本是一位Windows桌面应用程序开发工程师,对网络通信一知半解.一日老婆逛完某宝,问:"为什么他们知道我的地址呢,他们是怎么获取我的地址的呢?" 顺着这个问题我们的探秘 ...

  4. JAVA获取客户端IP地址

    在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的.但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实I ...

  5. WebService及WCF获取客户端IP,端口

    wcf获取客户端IP,端口 var context = OperationContext.Current; var properties = context.IncomingMessageProper ...

  6. asp.net获取客户端IP方法(转载)

    最近web获取客户端ip,看到下面这篇文章,转载过来,一起分享(转载地址:http://www.cnblogs.com/yejun/archive/2008/02/26/1082485.html) 通 ...

  7. (转)【ASP.NET开发】获取客户端IP地址 via C#

    [ASP.NET开发]获取客户端IP地址 via C# 说明:本文中的内容是我综合博客园上的博文和MSDN讨论区的资料,再通过自己的实际测试而得来,属于自己原创的内容说实话很少,写这一篇是为了记录自己 ...

  8. 获取客户端IP地址 via C#

    获取客户端IP地址 via C# 说明:本文中的内容是我综合博客园上的博文和MSDN讨论区的资料,再通过自己的实际测试而得来,属于自己原创的内容说实话很少,写这一篇是为了记录自己在项目中做过的事情,同 ...

  9. ASP.NET获取客户端信息,获取客户端IP等等

    山上明月 ASP.NET能知道的东西 获取服务器电脑名: Page.Server.ManchineName 获取用户信息: Page.User 获取客户端电脑名:Page.Request.UserHo ...

随机推荐

  1. Android Launcher分析和修改2——Icon修改、界面布局调整、壁纸设置

    上一篇文章说了如何修改Android自带Launcher2的默认界面设置(http://www.cnblogs.com/mythou/p/3153880.html). 今天主要是说说Launcher里 ...

  2. 我在tmux中最不可少的配置: 用鼠标切换窗口/调节分屏大小

    前两天在给另外一个团队帮忙时,看他们在Rails日志.代码文件.git文件系统里面来回穿梭,觉得他们太累了,于是就介绍了 tmux 给他们用.但只讲了一点基本的开窗口.分屏,没给讲太多技巧,因为一下子 ...

  3. java 虚拟机设置 Xms Xmx PermSize MaxPermSize

    Eclipse崩溃,错误提示:MyEclipse has detected that less than 5% of the 64MB of Perm Gen (Non-heap memory) sp ...

  4. vs2013 error LNK2005 已经在***.obj中定义

    错误解决办法: 方法一: 中文 项目--属性 ---连接器---输入                               附加依赖项    空格Nafxcwd.lib Libcmtd.lib ...

  5. [UFLDL] ConvNet

    二十三(Convolution和Pooling练习)  三十八(Stacked CNN简单介绍) 三十六(关于构建深度卷积SAE网络的一点困惑) 五十(Deconvolution Network简单理 ...

  6. SpringBoot Druid整合,SpringBoot 集成Druid

    SpringBoot Druid整合,SpringBoot 集成Druid ================================ ©Copyright 蕃薯耀 2018年4月8日 http ...

  7. 6. Oracle闪回特性

    Oracle 闪回 (flashback)是9i版本提供的新特性.这一特性:其他数据库(PostgreSQL,Mysql)是羡慕不已.对数据恢复提供非常便捷的方式.闪回技术通常用于快速简单恢复数据库中 ...

  8. VS设置DLL所在的调试目录

    如果一个项目依赖的DLL不想写在Path中,可以在 配置属性-调试-环境中添加 PATH=D:/OSG/bin;$(PATH)

  9. php MongoDB driver 查询实例

    //是否只查mx $mx_on_switch = I("post.mx_on_switch"); //mx模糊查询 $mx_vague_check = I("post.m ...

  10. React性能分析利器来了,妈妈再也不用担心我的React应用慢了(转)

    Profiler React16.5正式在devtool中加入了Profiler功能,用于收集每次变更导致的渲染时间,帮助开发者发现潜在的性能问题,有助于开发更高性能的React应用 官方博客 如何使 ...