1

所以我写了这个...

@Component
class AuthenticationFailureListener : ApplicationListener<AuthenticationFailureBadCredentialsEvent>{

    private val bruteForceProtection : BruteForceProtection

    @Inject
    constructor(bruteForceProtection: BruteForceProtection){
        this.bruteForceProtection = bruteForceProtection
    }

    override fun onApplicationEvent(event: AuthenticationFailureBadCredentialsEvent) {
        val webDetails = event.authentication.details as WebAuthenticationDetails
        val remoteAddress = webDetails.remoteAddress

        bruteForceProtection.recordFailedAttempt(remoteAddress)
    }
}

然后意识到我不知道 SpringX-Forwarded-For在安全上下文中设置远程地址时是否考虑了标头。

可以?

或者我如何将AuthenticationFailureBadCredentialsEvent它与它起源的远程地址相关联?

4

1 回答 1

2

来自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*标头做任何特别的事情。

因此,我们应用此类信息的选择是:

不幸ForwardedHeaderFilterX-Forwarded-For5.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"])
    }
}
于 2019-05-14T19:24:09.663 回答