经过反向代理Server如何优雅的获取用户IP

Posted 守钦在进步

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了经过反向代理Server如何优雅的获取用户IP相关的知识,希望对你有一定的参考价值。

我们有一个对外提供rest接口的服务,为了限制权限,我们对访问接口的机器进行IP鉴权,只有合法的IP才允许访问,但由于服务端是一个集群,我们采用了自研的类似于nginx的反向代理服务对集群进行负载均衡,由于用户不是直接与我们服务端进行通信,而是经过代理层进行中转,我们直接获取访问IP获取到的是代理层的机器IP,因此如何获取到用户真实的访问IP非常关键。


我们采用的是SpringMVC+Spring+Hibernate框架,HttpServletRequest带有一个获取访问IP的方法:

String requestIp = request.getRemoteAddr()

这种方法只能获取到的是直接访问的IP,也就是说我们服务端采用这种方法获取到的是代理层的IP。


其实处理对于这种通过代理访问服务的方式获取IP的问题非常简单,只需要代理层将用户的IP放到request的header里面,然后我们获取对应的header值就可以了,但这不是我们今天讨论的重点,我们今天讨论的是如何在Java的服务端优化的获取这个header。


开始我想到的是封装一个工具类,里面封装好获取用户访问的真实IP:

上面截图的工具类我兼容了多种类型的header标识,服务中好多地方都用到了用户的IP(鉴权、日志记录等),用到的时候就调用这个工具类解析一下,倒也挺方便的,但对于我这种追求代码效率的人来说,简直不能忍,每次都要解析,感觉影响效率,还有优化的空间~


后来为了防止多次解析,我想到了另一种方式,就是配置一个Filter,将IP解析好了然后作为一个Attribute放入request里面:

经过反向代理Server如何优雅的获取用户IP


然后什么地方用到IP就获取requestIp:

经过反向代理Server如何优雅的获取用户IP


上面的方法能够避免每次都解析一遍,但是感觉代码太冗余,每次还得强制转型,Attribute的Key:requestIp还得约定好,对于我这种还追求代码优雅的程序猿来说,还是不能忍!!!


问题解决不了,吃也吃不好睡也睡不香,我当时想,如果我直接调用request.getRemoteAddr()就能获取到用户的真实IP该多方便呀,各种查资料,车到山前必有路,终于在一些技术网站找到了一些思路。主要的思想是继承HttpServletRequestWrapper重新封装HttpServletRequest,重写getRemoteAddr()方法,废话不多说,直接上代码:

经过反向代理Server如何优雅的获取用户IP


然后继承Filter,写一个Servlet的拦截器:

经过反向代理Server如何优雅的获取用户IP


最后将该拦截器配置到web.xml的第一个filter位置,对于SpringBoot如何配置拦截器请自行研究:


后续用到用户的真实IP就可以直接用request.getRemoteAddr()获取,也不用约定什么,是不是特别爽~~~


以上是关于经过反向代理Server如何优雅的获取用户IP的主要内容,如果未能解决你的问题,请参考以下文章

nginx做反向代理负载均衡 Java怎么获取后端服务器获取用户IP

nginx做反向代理负载均衡 Java怎么获取后端服务器获取用户IP

nginx如何配置多IP的HTTP正向代理?

如何获取用户的真实IP

nginx 在多层代理下获取客户端IP

ngnix反向代理后获取用户真实ip