来自Spring Security#15.4 代理服务器配置:
使用代理服务器时,确保您已正确配置应用程序非常重要。例如,许多应用程序将有一个负载均衡器,它通过将请求https://example.com/
转发到应用程序服务器来响应请求。https://192.168.1:8080
如果没有适当的配置,应用程序服务器将不知道负载均衡器的存在,并将请求视为https://192.168.1:8080
客户端请求.
要解决此问题,您可以使用 RFC 7239 指定正在使用负载平衡器。要让应用程序知道这一点,您需要配置您的应用程序服务器以了解X-Forwarded
标头。例如 Tomcat 使用RemoteIpValve
, Jetty 使用ForwardedRequestCustomizer
. 或者,Spring 4.3+ 用户可以利用ForwardedHeaderFilter
.
Spring 框架和 Spring Security 本身都没有对X-Forwarded*
标头做任何特别的事情。
因此,我们应用此类信息的选择是:
不幸的ForwardedHeaderFilter
是X-Forwarded-For
,自5.1.7.RELEASE
.
所以剩下的选项是配置服务器。
由于您使用的是 tomcat,因此您可以提供一个server.tomcat.remote-ip-header
属性来考虑标头。
也可以看看ServerProperties
应用程序.yml:
server:
tomcat:
remote-ip-header: X-Forwarded-For
然后getRemoteAddr
将返回X-Forwarded-For
标题中存在的IP地址,该地址由WebAuthenticationDetails
它自己使用
WebAuthenticationDetails.java
public WebAuthenticationDetails(HttpServletRequest request) {
this.remoteAddress = request.getRemoteAddr();
HttpSession session = request.getSession(false);
this.sessionId = (session != null) ? session.getId() : null;
}
这是一个简单的测试:
IpController.kt
:
@RestController
class IpController {
@GetMapping("/ip")
fun getIp(request: HttpServletRequest) = mapOf("ip" to request.remoteAddr)
}
IpControllerTest.kt
@SpringBootTest(properties = ["server.tomcat.remote-ip-header=X-Forwarded-For"],
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class IpControllerTest {
@Autowired
private lateinit var testRestTemplate: TestRestTemplate
@Test
fun `uses ip from x-forwarded-for`() {
val httpHeaders = HttpHeaders()
httpHeaders["X-Forwarded-For"] = "8.8.8.8"
val httpEntity = HttpEntity<Any>(httpHeaders)
val map = testRestTemplate.exchange<Map<String, *>>("/ip", HttpMethod.GET, httpEntity)
.body!!
assertEquals("8.8.8.8", map["ip"])
}
}