设为首页 - 加入收藏 92站长网 (http://www.92zhanzhang.com)- 国内知名站长资讯网站,提供最新最全的站长资讯,创业经验,网站建设等!
热搜: 为什么 中国 苹果 系统
当前位置: 首页 > 运营中心 > 建站资源 > 优化 > 正文

Java面试-如何获取客户端真实IP

发布时间:2019-10-31 11:51 所属栏目:[优化] 来源:健程之道
导读:在进行一些小游戏开发时,我们经常比较关注的一个功能便是分享。针对分享,我们希望能根据各个城市或者地区,能有不同的分享文案,辨识地区的功能如果由服务器来完成的话,我们就需要知道客户端的真实IP。今天我们就来看看服务器是如何获取到客户端的真实I

在进行一些小游戏开发时,我们经常比较关注的一个功能便是分享。针对分享,我们希望能根据各个城市或者地区,能有不同的分享文案,辨识地区的功能如果由服务器来完成的话,我们就需要知道客户端的真实IP。今天我们就来看看服务器是如何获取到客户端的真实IP的。

Java面试-如何获取客户端真实IP

nginx配置

首先,一个请求肯定是可以分为请求头和请求体的,而我们客户端的IP地址信息一般都是存储在请求头里的。如果你的服务器有用Nginx做负载均衡的话,你需要在你的location里面配置X-Real-IP和X-Forwarded-For请求头:

  1. location?^~?/your-service/?{?
  2. proxy_set_header?X-Real-IP?$remote_addr;?
  3. proxy_set_header?X-Forwarded-For?$proxy_add_x_forwarded_for;?
  4. proxy_pass?http://localhost:60000/your-service/;?
  5. }?

1. X-Real-IP

在《实战nginx》中,有这么一句话:

这句话的意思是说,当你使用了nginx反向服务器后,在web端使用request.getRemoteAddr()(本质上就是获取$remote_addr),取得的是nginx的地址,即$remote_addr变量中封装的是nginx的地址,当然是没法获得用户的真实ip的。但是,nginx是可以获得用户的真实ip的,也就是说nginx使用$remote_addr变量时获得的是用户的真实ip,如果我们想要在web端获得用户的真实ip,就必须在nginx里作一个赋值操作,即我在上面的配置:

  1. proxy_set_header?X-Real-IP?$remote_addr;?

2. X-Forwarded-For

X-Forwarded-For变量,这是一个squid开发的,用于识别通过HTTP代理或负载平衡器原始IP一个连接到Web服务器的客户机地址的非rfc标准,如果有做X-Forwarded-For设置的话,每次经过proxy转发都会有记录,格式就是client1,proxy1,proxy2以逗号隔开各个地址,由于它是非rfc标准,所以默认是没有的,需要强制添加。在默认情况下经过proxy转发的请求,在后端看来远程地址都是proxy端的ip 。也就是说在默认情况下我们使用request.getAttribute("X-Forwarded-For")获取不到用户的ip,如果我们想要通过这个变量获得用户的ip,我们需要自己在nginx添加配置:

  1. proxy_set_header?X-Forwarded-For?$proxy_add_x_forwarded_for;?

意思是增加一个$proxy_add_x_forwarded_for到X-Forwarded-For里去,注意是增加,而不是覆盖,当然由于默认的X-Forwarded-For值是空的,所以我们总感觉X-Forwarded-For的值就等于$proxy_add_x_forwarded_for的值,实际上当你搭建两台nginx在不同的ip上,并且都使用了这段配置,那你会发现在web服务器端通过request.getAttribute("X-Forwarded-For")获得的将会是客户端ip和第一台nginx的ip。

3. 那么$proxy_add_x_forwarded_for又是什么?

$proxy_add_x_forwarded_for变量包含客户端请求头中的X-Forwarded-For与$remote_addr两部分,他们之间用逗号分开。

举个例子,有一个web应用,在它之前通过了两个nginx转发,www.linuxidc.com即用户访问该web通过两台nginx。

在第一台nginx中,使用:

  1. proxy_set_header?X-Forwarded-For?$proxy_add_x_forwarded_for;?

现在的$proxy_add_x_forwarded_for变量的X-Forwarded-For部分是空的,所以只有$remote_addr,而$remote_addr的值是用户的ip,于是赋值以后,X-Forwarded-For变量的值就是用户的真实的ip地址了。

到了第二台nginx,使用:

  1. proxy_set_header?X-Forwarded-For?$proxy_add_x_forwarded_for;?

现在的$proxy_add_x_forwarded_for变量,X-Forwarded-For部分包含的是用户的真实ip,$remote_addr部分的值是上一台nginx的ip地址,于是通过这个赋值以后现在的X-Forwarded-For的值就变成了“用户的真实ip,第一台nginx的ip”,这样就清楚了吧。

服务器获取真实IP

代码为:

  1. public?static?String?getIpAddress(HttpServletRequest?request)?{?
  2. String?Xip?=?request.getHeader("X-Real-IP");?
  3. String?XFor?=?request.getHeader("X-Forwarded-For");?
  4. if?(!Strings.isNullOrEmpty(XFor)?&&?!"unKnown".equalsIgnoreCase(XFor))?{?
  5. //多次反向代理后会有多个ip值,第一个ip才是真实ip?
  6. int?index?=?XFor.indexOf(",");?
  7. if?(index?!=?-1)?{?
  8. return?XFor.substring(0,?index);?
  9. }?else?{?
  10. return?XFor;?
  11. }?
  12. }?
  13. XFor?=?Xip;?
  14. if?(!Strings.isNullOrEmpty(XFor)?&&?!"unKnown".equalsIgnoreCase(XFor))?{?
  15. return?XFor;?
  16. }?
  17. if?(Strings.nullToEmpty(XFor).trim().isEmpty()?||?"unknown".equalsIgnoreCase(XFor))?{?
  18. XFor?=?request.getHeader("Proxy-Client-IP");?
  19. }?
  20. if?(Strings.nullToEmpty(XFor).trim().isEmpty()?||?"unknown".equalsIgnoreCase(XFor))?{?
  21. XFor?=?request.getHeader("WL-Proxy-Client-IP");?
  22. }?
  23. if?(Strings.nullToEmpty(XFor).trim().isEmpty()?||?"unknown".equalsIgnoreCase(XFor))?{?
  24. XFor?=?request.getHeader("HTTP_CLIENT_IP");?
  25. }?
  26. if?(Strings.nullToEmpty(XFor).trim().isEmpty()?||?"unknown".equalsIgnoreCase(XFor))?{?
  27. XFor?=?request.getHeader("HTTP_X_FORWARDED_FOR");?
  28. }?
  29. if?(Strings.nullToEmpty(XFor).trim().isEmpty()?||?"unknown".equalsIgnoreCase(XFor))?{?
  30. XFor?=?request.getRemoteAddr();?
  31. }?
  32. return?XFor;?
  33. }?

【免责声明】本站内容转载自互联网,其相关言论仅代表作者个人观点绝非权威,不代表本站立场。如您发现内容存在版权问题,请提交相关链接至邮箱:bqsm@foxmail.com,我们将及时予以处理。

网友评论
推荐文章