SLB+Tomcat时request.RemoteAddr无法获取正确的客户端IP的问题解决方案

# 前情提要

将CAS部署到阿里云,使用SLB进行前端负载以及SSL,后端使用TOMCAT作为应用服务器。

按照常规方式部署上去之后,遇到如下问题:

1. SSL下使用redirect,自动跳转到80端口。

2. CAS无法获取到客户端的IP,Cookies校验出错,导致单点登录功能失效。

# 查找原因

1. TOMCAT默认情况下的redirect会是80

2. CAS的Cookies检查以及写入程序使用request.getRemoteAddr()获取到的都是SLB的IP,并非实际客户端的IP,而且SLB的IP不固定(貌似阿里的SLB是一个N多台机器的玩意,每次一个页面请求过来,每个资源的请求IP都不同),我使用的杭州的SLB,IP段在100.97.*.*这个范围。

# 解决问题

1. 设定TOMCAT的使用前端代理模式,解决TOMCAT中程序的redirect没有跳转到SSL的问题。

在server.xml中找到对外开放的Connector,我的是用的NIO-8080

<Connector port="8080"

  proxyName="这里是域名"

  proxyPort="443"

  scheme="https"

  secure="true"

  protocol="org.apache.coyote.http11.Http11NioProtocol"

  connectionTimeout="20000" URIEncoding="UTF-8" useBodyEncodingForURI="true"

  redirectPort="8443" />

上述的含义是,

SLB的域名是proxyName

SLB对外端口是proxyPort

SLB使用的协议是https

SLB是否开启SSL:secure

2. 设定X-Forwarded过滤器

在server.xml中的<Engine>元素下增加如下内容:

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

  internalProxies="100\.97\.\d{1,3}\.\d{1,3}" />

internalProxies的意思是:TOMCAT仅接受这个IP段过来的请求中的X-Forwarded系列的值覆写为Remote_Addr等。加了这个过滤器之后使用request.getRemoteAddr()就可以获取到正确的客户端IP了。需要注意的是,这个IP段需要根据你所用的SLB来写。

在TOMCAT里,internalProxies的默认值为(无法覆盖到SLB的IP段):

10\.\d{1,3}\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3}|169\.254\.\d{1,3}\.\d{1,3}|127\.\d{1,3}\.\d{1,3}\.\d{1,3}|172\.1[6-9]{1}\.\d{1,3}\.\d{1,3}|172\.2[0-9]{1}\.\d{1,3}\.\d{1,3}|172\.3[0-1]{1}\.\d{1,3}\.\d{1,3} 

特别注意:

这个<Value>一定要写在<Engine>元素下!

这个<Value>一定要写在<Engine>元素下!

这个<Value>一定要写在<Engine>元素下!

我查了很多网上的资料,都是说在server.xml里面加上这个<Value>,于是我看到Tomcat有默认定义一个<Value>在<Host>里面,于是我也跟着写里面,但是就是不生效。然后我特姆调试了两天,结果一直不生效,最后在TOMCAT文档里找到这么一句话:

This Valve may be used at the EngineHost or Context level as required. Normally, this Valve would be used at the Engine level.

其他参数请参考Tomcat的文档:

https://tomcat.apache.org/tomcat-8.0-doc/config/valve.html#Remote_Address_Filter

希望此篇能给有需要的人带来帮助。

时间: 2024-12-11 01:28:42

SLB+Tomcat时request.RemoteAddr无法获取正确的客户端IP的问题解决方案的相关文章

ASP.NET获取真正的客户端IP地址的6种方法_实用技巧

在ASP中使用 Request.ServerVariables("REMOTE_ADDR") 来取得客户端的IP地址,但如果客户端是使用代理服务器来访问,那取到的就是代理服务器的IP地址,而不是真正的客户端IP地址. 要想透过代理服务器取得客户端的真实IP地址,就要使用 Request.ServerVariables("HTTP_X_FORWARDED_FOR") 来读取. 不过要注意的事,并不是每个代理服务器都能用 Request.ServerVariables(

ip网址怎么获取客户端ip地址

问题描述 比如地址是:1.51.23.111/index.aspx没有域名怎么获取客户端ip地址///<summary>///获取远程访问用户的Ip地址///</summary>///<returns>返回Ip地址</returns>protectedstringGetIps(){stringloginip="";//Request.ServerVariables[""]--获取服务变量集合if(Request.Ser

关于spring mvc注解的使用,运行tomcat时出错

问题描述 关于spring mvc注解的使用,运行tomcat时出错 spring-mvc.xml的代码 <!--开启注解扫描 --> <context:component-scan base-package="com.tarena"/> <!--开启MVC注解扫描 --> <mvc:annotation-driven/> <!--定义视图解析器ViewResolver --> <bean id="viewRe

jdk-idea中运行tomcat时出现这个,怎么搞

问题描述 idea中运行tomcat时出现这个,怎么搞 D:apache-tomcat-9.0.0.M1incatalina.bat run Using CATALINA_BASE: "C:UsersAdministrator.IntelliJIdea14system omcatUnnamed_FjdsSVN_2" Using CATALINA_HOME: "D:apache-tomcat-9.0.0.M1" Using CATALINA_TMPDIR: "

ajaxfileupload上传第一个文件的操作后再次上传时 request里面还是第一个文件的数据

问题描述 ajaxfileupload上传第一个文件的操作后再次上传时 request里面还是第一个文件的数据 DiskFileItemFactory diskFactory = new DiskFileItemFactory(); // threshold 极限.临界值,即硬盘缓存 10M diskFactory.setSizeThreshold(10 * 1024 * 1024); // repository 贮藏室,即临时文件目录 diskFactory.setRepository(new

《Adobe After Effects CC完全剖析》——获取正确的设置

获取正确的设置 After Effects 包含了一系列你必须理解的设置,以避免陷入不知在何时就要对它们进行修正的"战斗"中.这些设置都是有章可循的,例如如何处理时间.色深.透明度.像素宽高比和场数据等.它们不一定是有趣的工作,但这就像是引力,它们是恒定不变的,即使引力限制了自由飞行,但却可以帮助你顺利着陆. 项目设置 在"项目设置"(Project Settings)对话框中(Ctrl+Alt+Shift+K/Cmd+Opt+Shift+K快捷键)包含了3个基本部

tomcat-为什么我的myeclipse2014使用自己配置的Tomcat时,无法部署项目

问题描述 为什么我的myeclipse2014使用自己配置的Tomcat时,无法部署项目 配置文件和错误信息如上,尝试百度的好多方法,都得不到解决,谁能帮我看看,谢谢啦. 解决方案 感谢大家,我找到问题了,myeclipse2014配置自己安装的tomcat要把tomcat安装在某盘(我安装在C盘)根目录,如:C:Tomcat 7.0.以前安装在默认路径下,老出错.现在好啦,如果还有其他朋友遇到这个问题,就试试重新安装tomcat到根目录吧. 解决方案二: tomcat中无法部署myeclips

服务器启动tomcat时问题

问题描述 服务器启动tomcat时问题 在服务器启动tomcat时,会出现如下截图所示的蓝屏现象,这种现象是tomcat导致的还是本身的硬件或者驱动不对造成的? 解决方案 是本身的硬件或者驱动不对造成的.Tomcat只是诱因.不过,有很多软件都有这嫌疑. 解决方案二: 这和tomcat没关系吧 解决方案三: http://zm12.sm-img2.com/?src=http%3A%2F%2Fwww.beihaiting.com%2Fa%2FYNJD%2FYJGZ%2F2014%2F0403%2F

alarm-在闹钟响起时从pending intent获取requestCode

问题描述 在闹钟响起时从pending intent获取requestCode 当闹钟响起时,如何从 Receiver 类或者 Activity 类的 pending intent 中获取 requestCode? alarmMgr= (AlarmManager)getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(this BroadcastReceiver_Class.class); /*intent.putE