Associating an `AuthenticationFailureBadCredentialsEvent` with the remote address in the presence of XFF headers

前端 未结 1 1104
慢半拍i
慢半拍i 2021-01-23 16:03

So I wrote this ...

@Component
class AuthenticationFailureListener : ApplicationListener{

    private val bruteF         


        
相关标签:
1条回答
  • 2021-01-23 16:28

    From Spring Security#15.4 Proxy Server Configuration:

    When using a proxy server it is important to ensure that you have configured your application properly. For example, many applications will have a load balancer that responds to request for https://example.com/ by forwarding the request to an application server at https://192.168.1:8080 Without proper configuration, the application server will not know that the load balancer exists and treat the request as though https://192.168.1:8080 was requested by the client.

    To fix this you can use RFC 7239 to specify that a load balancer is being used. To make the application aware of this, you need to either configure your application server aware of the X-Forwarded headers. For example Tomcat uses the RemoteIpValve and Jetty uses ForwardedRequestCustomizer. Alternatively, Spring 4.3+ users can leverage ForwardedHeaderFilter.

    Neither Spring framework nor Spring Security itself do anything special about X-Forwarded* headers.

    So our options to apply such information are:

    • exposing the ForwardedHeaderFilter
    • configuring the server

    Unfortunately ForwardedHeaderFilter does not inspect X-Forwarded-For header as of 5.1.7.RELEASE.

    So the option left is to configure server.

    Since you're using tomcat you can supply a server.tomcat.remote-ip-header property to take the header into account.

    See also ServerProperties

    application.yml:

    server:
      tomcat:
        remote-ip-header: X-Forwarded-For
    

    then getRemoteAddr will return the ip address present in X-Forwarded-For header which is used by WebAuthenticationDetails itself

    WebAuthenticationDetails.java

    public WebAuthenticationDetails(HttpServletRequest request) {
        this.remoteAddress = request.getRemoteAddr();
    
        HttpSession session = request.getSession(false);
        this.sessionId = (session != null) ? session.getId() : null;
    }
    

    Here is a test a simple test:

    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"])
        }
    }
    
    0 讨论(0)
提交回复
热议问题