nginx反向代理后应用程序如何获取客户端真实IP?

nginx反向代理后应用程序如何获取客户端真实IP?

Nginx反向代理后,Servlet应用通过request.getRemoteAddr()取到的IP是Nginx的IP地址,并非客户端真实IP,通过request.getRequestURL()获取的域名、协议、端口都是Nginx访问Web应用时的域名、协议、端口,而非客户端浏览器地址栏上的真实域名、协议、端口。

Nginx的反向代理实际上是客户端和真实的应用服务器之间的一个桥梁,客户端(一般是浏览器)访问Nginx服务器,Nginx再去访问Web应用服务器。对于Web应用来说,这次HTTP请求的客户端是Nginx而非真实的客户端浏览器,如果不做特殊处理的话,Web应用会把Nginx当作请求的客户端,获取到的客户端信息就是Nginx的一些信息。

解决这个问题要从两个方面来解决:  1. 由于Nginx是代理服务器,所有客户端请求都从Nginx转发到Tomcat,如果Nginx不把客户端真实IP、域名、协议、端口告诉Tomcat,那么Tomcat应用是永远不会知道这些信息的,所以需要Nginx配置一些HTTP Header来将这些信息告诉被代理的Tomcat;  2. Tomcat这一端,不能再傻乎乎的获取直接和它连接的客户端(也就是Nginx)的信息,而是要从Nginx传递过来的HTTP Header中获取客户端信息。

Nginx

在代理的每个location处添加以下配置:

 proxy_set_header Host $http_host;
 
 proxy_set_header X-Real-IP $remote_addr;
 
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 
 proxy_set_header X-Forwarded-Proto $scheme;
 

解释以下上面的配置,以上配置是在Nginx反向代理的时候,添加一些请求Header。  1. Host包含客户端真实的域名和端口号;  2. X-Forwarded-Proto表示客户端真实的协议(http还是https);  3. X-Real-IP表示客户端真实的IP;  4. X-Forwarded-For这个Header和X-Real-IP类似,但它在多层代理时会包含真实客户端及中间每个代理服务器的IP。

配置到这一步后,还不能彻底解决问题。tomcat也需要配置

如果你在网上搜索“Java如何获取客户端真实IP”,搜索到的解决方案大多是通过获取HTTP请求头request.getHeader("X-Forwarded-For")request.getHeader("X-Real-IP")来实现,也就是上面在Nginx上配置的Header,这种方案获取的结果的确是正确的,但觉得并不优雅。因为既然Servlet API提供了request.getRemoteAddr()方法获取客户端IP,那么无论有没有用反向代理对于代码编写者来说应该是透明的。下面介绍一种更加优雅的方式。

使用Tomcat作为应用服务器,可以通过配置Tomcat的server.xml文件,在Host元素内最后加入:即可

<Valve className="org.apache.catalina.valves.RemoteIpValve" />

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏开发之途

重拾Java(3)-异常处理

异常是运行时在代码序列中引起的非正常状态。在不支持异常处理的计算机语言中,必须手动检查和处理错误,Java语言则采用面向对象的方式管理运行时错误。

7920
来自专栏itsoeasy

java下使用openssl生成公私钥

compatible with the PKCS#1 RSAPrivateKey or SubjectPublicKeyInfo format.

23610
来自专栏后台及大数据开发

webService学习之路(三):springMVC集成CXF后调用已知的wsdl接口

webService学习之路一:讲解了通过传统方式怎么发布及调用webservice

49130
来自专栏影子

关于Springmvc中include与Sitemesh装饰器的基本使用

!!!转载请注明出处=>http://www.cnblogs.com/funnyzpc/p/7283443.html

10220
来自专栏Java职业技术分享

阿里的Spring框架面试题到底有多难?这五大问题你又掌握了多少!

还在机械地打代码?我们很多开发者在开发 Spring 的程序的时候,很多的情况下,都是被动的接受了前辈们为我们做好的 Spring 特性案例。这样以来,确实在很...

16100
来自专栏开发之途

重拾Java(1)-基本数据类型与字面值

Java是一种强类型化的语言,每个变量都有一种类型,每个表达式也都有一种类型,并且每一种类型都是严格定义的。所有的赋值操作不管是显式的还是在方法中调用中通过参数...

9830
来自专栏Android源码框架分析

Android可见APP的不可见任务栈(TaskRecord)销毁分析

Android依托Java型虚拟机,OOM是经常遇到的问题,那么在快达到OOM的时候,系统难道不能回收部分界面来达到缩减开支的目的码?在系统内存不足的情况下,可...

17120
来自专栏后台及大数据开发

java 导出数据为word文档(保持模板格式)

①:设计好word文档格式,需要用数据填充的地方用便于识别的长字符串替换  如  aaaaaaaaaaaaaaaa

89620
来自专栏后台及大数据开发

Java开发中的23种设计模式详解(转)

                                  ——可复用面向对象软件的基础

8820
来自专栏杨飞@益术

java实现推送通知给iphone

    privatestatic String host = "gateway.sandbox.push.apple.com";     privat...

18010

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励