在进行一些小游戏开发时,咱们常常比较关注的一个功能即是分享。针对分享,咱们但愿能根据各个城市或者地区,能有不一样的分享文案,辨识地区的功能若是由服务器来完成的话,咱们就须要知道客户端的真实IP。今天咱们就来看看服务器是如何获取到客户端的真实IP的。
<!-- more -->php
首先,一个请求确定是能够分为请求头和请求体的,而咱们客户端的IP地址信息通常都是存储在请求头里的。若是你的服务器有用Nginx作负载均衡的话,你须要在你的location里面配置X-Real-IP
和X-Forwarded-For
请求头:java
location ^~ /your-service/ { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://localhost:60000/your-service/; }
在《实战nginx》中,有这么一句话:linux
通过反向代理后,因为在客户端和web服务器之间增长了中间层,所以web服务器没法直接拿到客户端的ip,经过$remote_addr变量拿到的将是反向代理服务器的ip地址。
这句话的意思是说,当你使用了nginx反向服务器后,在web端使用request.getRemoteAddr()
(本质上就是获取$remote_addr
),取得的是nginx的地址,即$remote_addr
变量中封装的是nginx的地址,固然是无法得到用户的真实ip的。可是,nginx是能够得到用户的真实ip的,也就是说nginx使用$remote_addr
变量时得到的是用户的真实ip,若是咱们想要在web端得到用户的真实ip,就必须在nginx里做一个赋值操做,即我在上面的配置:nginx
proxy_set_header X-Real-IP $remote_addr;
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添加配置:web
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。apache
那么$proxy_add_x_forwarded_for
又是什么?segmentfault
$proxy_add_x_forwarded_for
变量包含客户端请求头中的X-Forwarded-For
与$remote_addr
两部分,他们之间用逗号分开。后端
举个例子,有一个web应用,在它以前经过了两个nginx转发,www.linuxidc.com
即用户访问该web经过两台nginx。缓存
在第一台nginx中,使用:服务器
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,使用:
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”,这样就清楚了吧。
代码为:
public static String getIpAddress(HttpServletRequest request) { String Xip = request.getHeader("X-Real-IP"); String XFor = request.getHeader("X-Forwarded-For"); if (!Strings.isNullOrEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)) { //屡次反向代理后会有多个ip值,第一个ip才是真实ip int index = XFor.indexOf(","); if (index != -1) { return XFor.substring(0, index); } else { return XFor; } } XFor = Xip; if (!Strings.isNullOrEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)) { return XFor; } if (Strings.nullToEmpty(XFor).trim().isEmpty() || "unknown".equalsIgnoreCase(XFor)) { XFor = request.getHeader("Proxy-Client-IP"); } if (Strings.nullToEmpty(XFor).trim().isEmpty() || "unknown".equalsIgnoreCase(XFor)) { XFor = request.getHeader("WL-Proxy-Client-IP"); } if (Strings.nullToEmpty(XFor).trim().isEmpty() || "unknown".equalsIgnoreCase(XFor)) { XFor = request.getHeader("HTTP_CLIENT_IP"); } if (Strings.nullToEmpty(XFor).trim().isEmpty() || "unknown".equalsIgnoreCase(XFor)) { XFor = request.getHeader("HTTP_X_FORWARDED_FOR"); } if (Strings.nullToEmpty(XFor).trim().isEmpty() || "unknown".equalsIgnoreCase(XFor)) { XFor = request.getRemoteAddr(); } return XFor; }
咱们来看看各个请求头的含义
nginx代理通常会加上此请求头。
这是一个Squid
开发的字段,只有在经过了HTTP代理或者负载均衡服务器时才会添加该项。
这个通常是通过apache http服务器的请求才会有,用apache http作代理时通常会加上Proxy-Client-IP
请求头,而WL-Proxy-Client-IP
是它的weblogic插件加上的头。
有些代理服务器会加上此请求头。在网上搜了一下,有一个说法是:
这是普通的 http header,伪造起来很容易,不要轻易信任用户输入。 curl -H 'client-ip: 8.8.8.8' lidian.club/phpinfo.php | grep _SERVER 你就能看到 _SERVER["HTTP_CLIENT_IP"] 了。 client-ip 和 client-host 是在 NAPT 还没普及的年代,企业内网假设的 http 透明代理,传给服务器的 header,只有极少数厂家用过,历来不是标准,也历来没成为过事实标准。 (你们最熟悉的事实标准就是 x-forwarded-for) 后来出现的 web proxy 也没见用过这个 header。 TCP/IP Illustrated Vol 3 没有讲过这个 header,网上的传言不可信。 可考的最先痕迹出如今2005年,日本一部 Perl/CGI 秘籍(9784798010779,270页)经过 client-ip 与 via 两个 header 屏蔽代理用户访问。
简称XFF头,它表明客户端,也就是HTTP的请求端真实的IP,只有在经过了HTTP 代理(好比APACHE代理)或者负载均衡服务器时才会添加该项。它不是RFC中定义的标准请求头信息,在squid缓存代理服务器开发文档中能够找到该项的详细介绍。若是有该条信息, 说明您使用了代理服务器,地址就是后面的数值。能够伪造。标准格式以下:X-Forwarded-For: client1, proxy1, proxy2
以上就是我在处理客户端真实IP的方法,若是你有什么意见或者建议,能够在下方留言。
有兴趣的话能够关注个人公众号或者头条号,说不定会有意外的惊喜。