最近在实施apache2.2+mod_proxy+jetty7.2.0时遇到的一个诡异的问题
现象:
直接访问应用(A)能正常显示页面;但是通过应用(B)再代理访问A,则页面显示出错。
A的域名benni82.a.com
===============
B的域名www.b.com
apache rewrite配置如下:
RewriteRule ^/proxy/(.*)$ $1 [P,L]
用户通过访问 http://www.b.com/proxy/http://benni82.a.com 来访问应用A,就显示错误页面。
而用户直接访问 http://benni.a.com 正常显示页面。
A应用的逻辑上依赖request.getServerName()
分析:
当通过mod_proxy代理访问时,http请求头会带上一些额外的信息
X-Forwarded-For: 10.20.156.2, 10.20.156.3
X-Forwarded-Host: www.b.com, benni82.a.com
X-Forwarded-Server: www.b.com, www.a.com
X-Forwarded-For的内容从左到右依次是,用户的ip,第一个代理ip
X-Forwarded-Host依次是,第一次代理时请求头的Host值,第二次代理时请求头的Host值
X-Forwarded-Server依次是:第一个代理的ServerName,第二个代理的ServerName(取自apache ServerName指令的设值)
而为了解决获取客户端原始ip地址,我们开启了jetty的forwarded功能。
开启该功能后,jetty在解析请求头时会优先使用X-Forwarded的内容。
-
会拿X-Forwarded-For最左边的ip地址(10.20.156.2)作为客户端原始ip,设置request.remoteAddr
-
会拿X-Forwarded-Host的最左边的值(www.b.com),设置request.serverName,
-
如果X-Forwarded-Host没有内容,会拿X-Forwarded-Server的最左边的值(crm.cn.alibaba-inc.com),设置request.serverName。
所以最后应用获取的ServerName时第一次代理时的Host,即www.b.com,页面返回错误。
而直接访问http://benni82.a.com时,
相应的值如下:
X-Forwarded-Host: benni82.a.com
X-Forwarded-Server: www.a.com
最后应用获取的serverName是benni82.a.com,和请求头的host一致,页面能正常返回。
解决方案:
connector配置中添加两行
<Call name="addConnector">
<Arg>
<New class="org.eclipse.jetty.server.nio.SelectChannelConnector">
<Set name="port"><Property name="jetty.port" default="7001"/></Set>
<Set name="forwarded">true</Set>
<Set name="forwardedServerHeader">ignore</Set>
<Set name="forwardedHostHeader">ignore</Set>
<Set name="maxIdleTime">600000</Set>
</New>
</Arg>
</Call>
forwardedServerHeader默认是:
X-Forwarded-Server
forwardedHostHeader默认值:
X-Forwarded-Host
目的阻止jetty用
X-Forwarded-Host或
X-Forwarded-Server的内容复写ServerName
.
protected void checkForwardedHeaders(EndPoint endpoint, Request request) throws IOException
{
HttpFields httpFields = request.getConnection().getRequestFields();
// Retrieving headers from the request
String forwardedHost = getLeftMostValue(httpFields.getStringField(getForwardedHostHeader()));
String forwardedServer = getLeftMostValue(httpFields.getStringField(getForwardedServerHeader()));
String forwardedFor = getLeftMostValue(httpFields.getStringField(getForwardedForHeader()));
String forwardedProto = getLeftMostValue(httpFields.getStringField(getForwardedProtoHeader()));
if (_hostHeader != null)
{
// Update host header
httpFields.put(HttpHeaders.HOST_BUFFER,_hostHeader);
request.setServerName(null);
request.setServerPort(-1);
request.getServerName();
}
else if (forwardedHost != null)
{
// Update host header
httpFields.put(HttpHeaders.HOST_BUFFER,forwardedHost);
request.setServerName(null);
request.setServerPort(-1);
request.getServerName();
}
else if (forwardedServer != null)
{
// Use provided server name
request.setServerName(forwardedServer);
}
if (forwardedFor != null)
{
request.setRemoteAddr(forwardedFor);
InetAddress inetAddress = null;
if (_useDNS)
{
try
{
inetAddress = InetAddress.getByName(forwardedFor);
}
catch (UnknownHostException e)
{
Log.ignore(e);
}
}
request.setRemoteHost(inetAddress == null?forwardedFor:inetAddress.getHostName());
}
if (forwardedProto != null)
{
request.setScheme(forwardedProto);
}
}
分享到:
相关推荐
网上看到jetty-proxy有反相代理功能,根据很多网页配置并未成功,感觉是jetty版本更新比较快,文档跟不上,所以把我调试通过的上传一下。jetty版本9.4.6
使用jetty实现websocket功能,jetty已经集成了websocket的标准方法。
jetty-security-9.4.8.v20171121.jar,jetty-io-9.4.8.v20171121.jar,jetty-continuation-9.4.8.v20171121.jar,jetty-client-9.4.8.v20171121.jar,jetty-jmx-9.4.8.v20171121.jar,jetty-plus-9.4.8.v20171121....
eclipse jetty插件,从...下载run-jetty-run.zip文件,解压后再编写个links文件丢到eclipse的dropins目录下即可,省去了使用eclipse update方式安装的麻烦。 link文件样例如: path=d:\\eclipse_plugins\\run-jetty-run
Jetty软件包内容: jetty-distribution-9.4.51.v20230217.tar.gz jetty-distribution-9.4.51.v20230217.zip jetty-home-10.0.15.tar.gz jetty-home-10.0.15.zip jetty-home-11.0.15.tar.gz jetty-home-11.0.15.zip ...
自己用jetty写的java小例子,在mac 环境下,具体的解说在:https://www.cnblogs.com/aspirant/p/9445542.html
jetty是什么 jetty配置 jetty使用 jetty嵌入 jetty启动 jetty部署 jetty教程 jetty嵌入式 jetty
jetty hot deploy.zip
把${jetty_home}/etc目录下的jetty.xml、webdefault.xml文件复制到${project_home}/jetty/etc目录中。 把${jetty_home}/lib/jsp-2.1目录复制到${project_home}/jetty/lib目录下(如果不复制jsp-2.1或jsp-2.0也可以...
Eclipse Jetty provides a Web server and javax.servlet container, plus support for HTTP/2, WebSocket, OSGi, JMX, JNDI, JAAS and many other integrations. These components are open source and available ...
最新jetty 事例,详细讲解jetty实用,开发,介绍。
.jetty
Maven下使用Jetty进行Debug maven 下面 debug 一直很好麻烦 本方是一种方法
jetty服务器,9.2版本适合java7+开发环境。 Jetty是一个纯粹的基于Java的网页服务器和Java Servlet容器。 尽管网页服务器通常用来为人们呈现文档,但是Jetty通常在较大的软件框架中用于计算机与计算机之间的通信。 ...
jetty嵌入式服务器开发所必须的jar包,本人使用jetty版本为6.1.3,jar包总数为9个,来自jetty:commons-el-1.0.jar,jasper-compiler-5.5.15,jasper-compiler-jdt-5.5.15.jar,jasper-runtime-5.5.15.jar,jetty-...
jetty-9.4.6
Jetty是一个纯Java实现的开源Servlet容器,Jetty也可以作为HTTP服务器和HTTP客户端,Jetty仪器轻巧...众所周知因为安全的原因,多数浏览器都限制了Ajax跨域请求和javascript加载的时候只能是与当前域下的应用进行交互。
spring boot内置jetty开发,附带一些基础小功能,比如上传下载文件,走马灯,图片预览等等。
jetty相关所有jar包,包含jar包: jetty-continuation-8.1.15.v20140411,jetty-http-8.1.15.v20140411,jetty-io-8.1.15.v20140411,jetty-security-8.1.15.v20140411,jetty-server-8.1.15.v20140411,jetty-util-8.1.15...
jetty实施手册