SpringBoot项目获取客户端IP
本文主要介绍了SpringBoot项目中如何获取真实客户端IP,在应用前侧有nginx或cdn时应该如何处理。
X-Forwarded-For
(简称XFF)是一个常见的(非正式使用的)传递真实用户IP的方式,其内容一般是:
1 | X-Forwarded-For: real_client_ip, proxy1_ip, proxy2_ip |
真实用户IP会被放在第一位
单独部署SpringBoot应用
当客户端直连SpingBoot时,可以直接简单的从HttpServletRequest
中的getRemoteAddr()
方法获取客户端IP
前端加一层Nginx代理
在Nginx中配置加入如下配置,会在http的请求头header中加入X-Forwarded-For
信息
1 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; |
另外还有一种配置方式
1 | proxy_set_header X-Forwarded-For $remote_addr; |
两种方式的区别为$proxy_add_x_forwarded_for
=$之前带的X-Forwarded-For信息, $remote_addr
Nginx在XFF信息中,把上一层的IP添加到了X-Forwarded-For信息的最后
所以正常情况下,从Nginx收到消息的XFF信息中,逗号分隔第一个ip为真实用户ip。
当用户带有人工添加XFF信息时,这些信息会被添加在XFF最前方,所以通过第一个IP来获取用户IP的方式不够合理。
在使用SpringBoot过程中,tomcat会默认使用RemoteIpValue
类来获取真实用户IP,这个类会处理XFF信息,尝试从后往前获取真实用户IP,这个获取过程会尝试跳过内网ip地址(例如127、172)等,并从XFF信息中删除掉,最后设置到Request
类的remoteAddr
属性中。所以在应用层直接从HttpServletRequest
中的getRemoteAddr()
方法获取客户端IP。这种方式合理性在于,认为中间多层的Nginx代理信息,均为内网环境,第一个非内网IP为本应用群所接收到的外网IP,也就是对本应用群来讲的用户IP。
这里还需要考虑一个问题,假如用户在请求中带入虚假XFF信息,那么实际过程中会把XFF信息放在最前,而真实IP放在最后。所以SpringBoot中获取的仍是正确的。所以这里无需处理。
最终结论
无论是单独部署还是在nginx之后,应用都直接从HttpServletRequest
中的getRemoteAddr()
方法获取客户端IP,即可得到真实IP。
假如多层代理在不同网络环境中,该种方式只能获取到最后一片可用区所收到的外网IP。如果有需要可以关闭tomcat自动获取XFF信息开关,并手动解析XFF信息。注意需要在第一层代理中,清除过滤掉用户带的自定义XFF信息,保证链路可寻。
SpringBoot项目获取客户端IP