问题描述
所以我写了这个...
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?
推荐答案
来自 Spring Security#15.4代理服务器配置:
要解决此问题,可以使用RFC 7239指定正在使用负载平衡器.为了使应用程序意识到这一点,您需要配置您的应用程序服务器以了解X-Forwarded
标头.例如,Tomcat使用RemoteIpValve
,而Jetty使用ForwardedRequestCustomizer
.另外, Spring 4.3+及更高版本的用户可以使用ForwardedHeaderFilter
.
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
.
Spring框架和Spring Security本身都不对X-Forwarded*
标头做任何特殊的事情.
Neither Spring framework nor Spring Security itself do anything special about X-Forwarded*
headers.
因此,我们应用这些信息的选项是:
So our options to apply such information are:
- 暴露
ForwardedHeaderFilter
- 配置服务器
不幸的是, ForwardedHeaderFilter
没有从5.1.7.RELEASE
开始检查X-Forwarded-For
标头 .
Unfortunately ForwardedHeaderFilter
does not inspect X-Forwarded-For
header as of 5.1.7.RELEASE
.
因此,剩下的选项是配置服务器.
So the option left is to configure server.
由于您使用的是tomcat,因此可以提供server.tomcat.remote-ip-header
属性以将标头考虑在内.
Since you're using tomcat you can supply a server.tomcat.remote-ip-header
property to take the header into account.
另请参见 ServerProperties
application.yml :
server:
tomcat:
remote-ip-header: X-Forwarded-For
然后 getRemoteAddr
将返回X-Forwarded-For
标头中存在的ip地址,该标头由 WebAuthenticationDetails
本身
then getRemoteAddr
will return the ip address present in X-Forwarded-For
header which is used by WebAuthenticationDetails
itself
WebAuthenticationDetails.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"])
}
}
这篇关于在存在XFF标头的情况下,将"AuthenticationFailureBadCredentialsEvent"与远程地址相关联的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!