在存在XFF标头的情况下,将"AuthenticationFailureBadCredentialsEvent"与远程地址相关联 [英] Associating an `AuthenticationFailureBadCredentialsEvent` with the remote address in the presence of XFF headers
问题描述
所以我写了这个...
So I wrote this ...
@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)
}
}
然后意识到我不知道在安全上下文中设置远程地址时,Spring是否使用X-Forwarded-For
标头.
Then realised I have no idea if Spring accounts for X-Forwarded-For
headers when setting the remote address in the security context.
是吗?
或者我如何将AuthenticationFailureBadCredentialsEvent
与它源自的远程地址相关联?
Or how would I associate the AuthenticationFailureBadCredentialsEvent
with the remote address it originated from?
推荐答案
来自
使用代理服务器时,确保已正确配置应用程序很重要.例如,许多应用程序将具有一个负载均衡器,该负载均衡器通过将请求转发到 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 要解决此问题,可以使用RFC 7239指定正在使用负载平衡器.为了使应用程序意识到这一点,您需要配置您的应用程序服务器以了解 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 Spring框架和Spring Security本身都不对 Neither Spring framework nor Spring Security itself do anything special about 因此,我们应用这些信息的选项是: So our options to apply such information are: Unfortunately 因此,剩下的选项是配置服务器. So the option left is to configure server. 由于您使用的是tomcat,因此可以提供 Since you're using tomcat you can supply a 另请参见 application.yml : 然后 then 这是一个简单的测试: 这篇关于在存在XFF标头的情况下,将"AuthenticationFailureBadCredentialsEvent"与远程地址相关联的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!https://192.168.1:8080
处的应用程序服务器来响应对https://example.com/
的请求,如果没有适当的配置,则应用程序服务器将不知道负载均衡器是否存在并将该请求视为尽管https://192.168.1:8080
是客户端请求的.
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.X-Forwarded
标头.例如,Tomcat使用RemoteIpValve
,而Jetty使用ForwardedRequestCustomizer
.另外, Spring 4.3+及更高版本的用户可以使用ForwardedHeaderFilter
. X-Forwarded
headers. For example Tomcat uses the RemoteIpValve
and Jetty uses ForwardedRequestCustomizer
. Alternatively, Spring 4.3+ users can leverage ForwardedHeaderFilter
.X-Forwarded*
标头做任何特殊的事情.X-Forwarded*
headers.
ForwardedHeaderFilter
ForwardedHeaderFilter
does not inspect X-Forwarded-For
header as of 5.1.7.RELEASE
. server.tomcat.remote-ip-header
属性以将标头考虑在内.server.tomcat.remote-ip-header
property to take the header into account.server:
tomcat:
remote-ip-header: X-Forwarded-For
getRemoteAddr
将返回X-Forwarded-For
标头中存在的ip地址,该标头由getRemoteAddr
will return the ip address present in X-Forwarded-For
header which is used by WebAuthenticationDetails
itselfWebAuthenticationDetails.java
WebAuthenticationDetails.java
public WebAuthenticationDetails(HttpServletRequest request) {
this.remoteAddress = request.getRemoteAddr();
HttpSession session = request.getSession(false);
this.sessionId = (session != null) ? session.getId() : null;
}
IpController.kt
:IpController.kt
:@RestController
class IpController {
@GetMapping("/ip")
fun getIp(request: HttpServletRequest) = mapOf("ip" to request.remoteAddr)
}
IpControllerTest.kt
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"])
}
}