如何在存在主机 header 时确定请求的真实服务器端口

How to determine a request's real serverPort when a Host header is present

我有一个启用了管理端点的 spring 启动应用程序。 这意味着应用程序在端口 8080 上启动,管理端点在端口 8081 上可用。

该应用程序使用 spring 安全性进行保护,但是,无需身份验证即可访问管理端点。所以我添加了一个请求匹配器来评估服务器端口(使用 request.getServerPort())以忽略对端口 8081 上的管理端点的所有请求。

现在碰巧当 Host header 存在时,header 的端口在 request.getServerPort() 中返回,而不是真正的服务器端口。

这意味着我可以使用带有端口 8081 的 Host header 访问应用程序并绕过 Spring 安全!?

为了清楚起见,示例:

curl localhost:8080
returns 401 (unauthorized, that's correct)

curl localhost:8081/health
returns 200 (found)

但是

curl -H "Host: localhost:8081" localhost:8080
returns 200 (wtf?) - because request.getServerPort() == 8081

curl -H "Host: localhost:8080" localhost:8081/health
returns 401 - because request.getServerPort() == 8080

问题是:如何确定应用程序接收请求的真实端口?

ServletRequest#getLocalName() returns local hostname.
ServletRequest#getLocalAddr() returns local IP.
ServletRequest#getLocalPort() returns local port.

为了更清楚,请参考: Get Application Server name or ip and port in Java