Objective: get the remote address of users (i.e. request.getRemoteAddr()) in Spring Boot web applications.
Introduction:
As known, the getRemoteAddr method returns the address of the immediate caller which might be the proxy server or any other servers in between the original user and the final destination server (if there's any). To find the real address of the user, one needs to look into other headers (e.g. X-Forwarded-For). However I found that Tomcat (which is our web container) has a filter called RemoteIpFilter that takes care of this issue by copying the original address, stored in another header (e.g. X-Forwarded-For) back so that calling request.getRemoteAddr() gives you the originl address.
I added the filter to the code and everything works just fine:
@Bean
FilterRegistrationBean<RemoteIpFilter> remoteIpFilter() {
val filter = new FilterRegistrationBean<>(new RemoteIpFilter());
filter.addUrlPatterns("/*");
return filter;
}
However, there's an issue; when the request is a multipart one, Spring rejects it with:
The request was rejected because the header value "multipart/mixed; boundary="----=_Part_0_blahblah"; charset=utf-8" is not allowed.
I can see that the exception is thrown because FilterChainProxy filter of Spring wraps the request in StrictFirewalledRequest that in turn, has some checks regarding what is allowed and what is not (e.g. the above content-type is not allowed).
I couldn't find a proper solution for the above issue, other than putting the RemoteIpFilter filter before FilterChainProxy filter:
// right before the tracing filter!
filter.setOrder(SleuthWebProperties.TRACING_FILTER_ORDER - 1);
Questions
- Is using
RemoteIpFiltera good idea? - Is there a better way to fix the above issue?
- What's the best order number for
RemoteIpFilter?
Thanks.