在Java Web应用程序中如何获取服务器名称

10

我有一个 Web 应用程序,用户需要在他们自己的 Java Web 服务器上部署(例如 Tomcat)。Web 应用程序的 Java 部分需要报告 Web 应用程序本身的 URL(例如 http://aServer.com:8080/MyApphttps://blah.blahSever/MyApp 的形式)。然而,由于许多用户使用端口转发和其他网络技术,Web 应用程序经常报告错误的名称。

我已尝试以下技术,但通常它们并不能生成用户需要的结果。

注意(request 是一个 HttpServletRequest)

request.getLocalAddr();    // Returns: 127.0.0.1
request.getLocalName();    // Returns: localhost
request.getServerName();   // Returns: localhost
request.getServerPort();   // Returns: 8080
request.getContextPath();  // Returns: /MyApp

request.getScheme();       // Returns: http

InetAddress.getLocalHost().getHostName();           // Returns: serverXXX-XXX-XXX-XX.xxxx-xxxxxxx.net
InetAddress.getLocalHost().getHostAddress();        // Returns: xxx.xxx.xxx.xxx (ip address)
InetAddress.getLocalHost().getCanonicalHostName();  // Returns: serverXXX-XXX-XXX-XX.xxxx-xxxxxxx.net

InetAddress的使用接近于我想要的,但由于我们在Apache2服务器中使用Server Aliases和ProxyPass,因此InetAddress的值是实际服务器的值,而不是别名的值。

我唯一想到的解决方案是让用户在属性文件中提供一个属性,Web应用程序在启动时读取该属性。如果设置了该属性,则使用该值返回完整的Web应用程序路径(例如serverUrl = https://blah.blahServer/MyApp)。这种技术可以工作,但需要为我的客户进行更多的部署工作。

有没有人有任何想法,可以实现一个更加优雅的解决方案呢?

谢谢, Phil


1
将地址放入系统属性中并使用。如果您将其放在不同的服务器上,请修改该属性。如果未设置该属性,则使应用程序拒绝启动。 - Kayaman
你尝试过 request.getRequestURL() 吗? - Mustafa Genç
@Mustafa Genc - 不幸的是,getRequestUrl只返回:http://localhost:8080/MyApp/ - 这很好而且完整(它包括http和端口和Web应用程序名称),但不幸的是返回了“localhost”! - Phil
@Kayaman - 我认为你的方法可能是我要采用的! - Phil
@Phil 这绝对是最简单的方法(并且效果很好,除非您经常切换域名)。 - Kayaman
3个回答

7

检查“host”请求头。大多数客户端都会添加该标头以指示它们正在尝试联系的主机。

这是用于虚拟主机的相同标头,因此这是相当标准的。在HTTP1.1请求中也是必需的。

事实上,您无法纯粹从服务器端获取值,因为用户可能已为您的服务器定义了自己的主机名。

request.getHeader("Host")

如果您的服务器位于Apache反向代理后面,请使用ProxyPreserveHost指令确保Host头部被完整保留。我相信其他反向代理也有类似的选项。


我尝试使用getHeader(“Host”)方法,但它只返回“localhost:8080”。我真的想要一个解决方案,不涉及通知客户需要修改他们的Apache代理或其他任何内容。我认为,就Pure Java而言,我所要求的实际上是不可能的。 - Phil
如果客户端没有发送用于联系您的主机名,则您无法知道它,因为它可能因客户端而异。当然,如果您想定义规范名称,那么情况就不同了,您应该只使用一些配置属性(许多应用程序都是这样做的)。至于本地主机,请使用Firebug(或类似工具)检查请求中发送的标头。如果确实是localhost,那么这意味着您的浏览器以某种方式将主机名切换为localhost,或者当然,您在url中真的使用了“localhost” :) - Joeri Hendrickx
4
host 请求头不安全,因为它可以被任何人更改。 - deiga
@deiga 任何人都可以更改任何一个头文件 -- 然而,由于主机没有单一的名称,因此关于客户端用作主机名与您联系的可靠来源最接近的事物是客户端本身。你只能冒险尝试。 - Joeri Hendrickx
“你只需要冒险一试”是我曾经读过的最糟糕的建议之一。任何人都不应该使用这种方法来确定他们的服务器名称。最安全的方法是将所需的值设置为配置属性,并在需要时从您的上下文/环境中读取它。这可能不是最有效的方法,但至少您不会公然暴露您的用户面临一些相当严重的安全威胁。 - Wrinn
@Wrinn 嗯,当然,但这假设你“需要”一个特定的值(正如你自己所说)。我想在绝大多数情况下(即在互联网上),你有一个规范的主机名,并且你更喜欢回答它 - 但对于一般情况,你无法知道客户端如何解析你的名称,除非询问它(它使用了哪个DNS,或者是私有的hostfile?)。此外,如果你要不信任主机头,则可以将任何类型的虚拟主机配置(这是相当常见的)抛出窗外... - Joeri Hendrickx

4
这对我解决了问题:
InetAddress.getLocalHost().getHostName();

0
我认为你的问题不是使用Java API访问所需值。例如,在Tomcat中,有一个包含一对行的server.xml文件。
<Engine name="Catalina" defaultHost="**localhost**">

<Host name="**localhost**"  appBase="webapps"  ...

如果你将localhost替换为你想要的名称,比如"myhost.com",并且Tomcat运行的主机知道自己的主机名,那么当你使用指定的主机名检索URL时,它将显示你所请求的名称。
此致敬礼

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接