【Nginx】如何获取客户端真实IP、域名、协议、端口?看这一篇就够了!

RemoteAddr: 127.0.0.1

URL: http://127.0.0.1:8080/test

可以发现,Servlet程序获取到的客户端IP是Nginx的IP而非浏览器所在机器的IP,获取到的URL是Nginx proxy_pass配置的URL组成的地址,而非浏览器地址栏上的真实地址。如果将Nginx用作https服务器反向代理后端的http服务,那么request.getRequestURL()获取的URL是http前缀的而非https前缀,无法获取到浏览器地址栏的真实协议。如果此时将request.getRequestURL()获取得到的URL用作拼接Redirect地址,就会出现跳转到错误的地址,这也是Nginx反向代理时经常出现的一个问题。

如何解决这些问题?


既然直接使用Nginx获取客户端信息存在问题,那我们该如何解决这个问题呢?

我们整体上需要从两个方面来解决这些问题:

(1)由于Nginx是代理服务器,所有客户端请求都从Nginx转发到Jetty/Tomcat,如果Nginx不把客户端真实IP、域名、协议、端口告诉Jetty/Tomcat,那么Jetty/Tomcat应用永远不会知道这些信息,所以需要Nginx配置一些HTTP Header来将这些信息告诉被代理的Jetty/Tomcat;

(2)Jetty/Tomcat这一端,不能再获取直接和它连接的客户端(也就是Nginx)的信息,而是要从Nginx传递过来的HTTP Header中获取客户端信息。

具体实践


配置nginx

首先,我们需要在Nginx的配置文件nginx.conf中添加如下配置。

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;

各参数的含义如下所示。

  • Host包含客户端真实的域名和端口号;

  • X-Forwarded-Proto表示客户端真实的协议(http还是https);

  • X-Real-IP表示客户端真实的IP;

  • X-Forwarded-For这个Header和X-Real-IP类似,但它在多层代理时会包含真实客户端及中间每个代理服务器的IP。

此时,再试一下request.getRemoteAddr()request.getRequestURL()的输出结果:

RemoteAddr: 127.0.0.1

URL: http://192.168.1.100/test

可以发现URL好像已经没问题了,但是IP还是本地的IP而非真实客户端IP。但是如果是用Nginx作为https服务器反向代理到http服务器,会发现浏览器地址栏是https前缀但是request.getRequestURL()获取到的URL还是http前缀,也就是仅仅配置Nginx还不能彻底解决问题。

通过Java方法获取客户端信息

仅仅配置Nginx不能彻底解决问题,那如何才能解决这个问题呢?一种解决方式就是通过Java方法获取客户端信息,例如下面的Java方法。

/***

  • 获取客户端IP地址;这里通过了Nginx获取;X-Real-IP

*/

public static String getClientIP(HttpServletRequest request) {

String fromSource = “X-Real-IP”;

String ip = request.getHeader(“X-Real-IP”);

if (ip == null || ip.length() == 0 || “unknown”.equalsIgnoreCase(ip)) {

ip = request.getHeader(“X-Forwarded-For”);

fromSource = “X-Forwarded-For”;

}

if (ip == null || ip.length() == 0 || “unknown”.equalsIgnoreCase(ip)) {

ip = request.getHeader(“Proxy-Client-IP”);

fromSource = “Proxy-Client-IP”;

}

if (ip == null || ip.length() == 0 || “unknown”.equalsIgnoreCase(ip)) {

ip = request.getHeader(“WL-Proxy-Client-IP”);

fromSource = “WL-Proxy-Client-IP”;

}

if (ip == null || ip.length() == 0 || “unknown”.equalsIgnoreCase(ip)) {

ip = request.getRemoteAddr();

fromSource = “request.getRemoteAddr”;

}

return ip;

}

这种方式虽然能够获取客户端的IP地址,但是我总感觉这种方式不太友好,因为既然Servlet API提供了request.getRemoteAddr()方法获取客户端IP,那么无论有没有用反向代理对于代码编写者来说应该是透明的。

接下来,我就分别针对Jetty服务器和Tomcat服务器为大家介绍下如何进行配置才能更加友好的获取客户端信息。

Jetty服务器

在Jetty服务器的jetty.xml文件中,找到httpConfig,加入配置:

重新启动Jetty,再用浏览器打开http://192.168.1.100/test测试,结果:

RemoteAddr: 192.168.1.100

URL: http://192.168.1.100/test

此时可发现通过request.getRemoteAddr()获取到的IP不再是127.0.0.1而是客户端真实IP,request.getRequestURL()获取的URL也是浏览器上的真实URL,如果Nginx作为https代理,request.getRequestURL()的前缀也会是https。

另外,Jetty将这个功能封装成一个模块:http-forwarded。如果不想改jetty.xml配置文件的话,也可以启用http-forwarded模块来实现。

例如可以通过命令行启动Jetty:

java -jar start.jar --module=http-forwarded

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

分享

这次面试我也做了一些总结,确实还有很多要学的东西。相关面试题也做了整理,可以分享给大家,了解一下面试真题,想进大厂的或者想跳槽的小伙伴不妨好好利用时间来学习。学习的脚步一定不能停止!

薪酬缩水,“裸辞”奋战25天三面美团,交叉面却被吊打,我太难了

Spring Cloud实战

薪酬缩水,“裸辞”奋战25天三面美团,交叉面却被吊打,我太难了

Spring Boot实战

薪酬缩水,“裸辞”奋战25天三面美团,交叉面却被吊打,我太难了

面试题整理(性能优化+微服务+并发编程+开源框架+分布式)
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
ng Cloud实战

[外链图片转存中…(img-xu6Nvezh-1713402303407)]

Spring Boot实战

[外链图片转存中…(img-sFy1SX2m-1713402303408)]

面试题整理(性能优化+微服务+并发编程+开源框架+分布式)
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值