【发布时间】:2013-12-07 03:47:06
【问题描述】:
我有 Spring MVC 应用程序,托管在 Tomcat 容器中。 Tomcat 以 NginX 为前端,因此我在 NginX 配置中明确设置了标头:
位置/{
proxy_passhttp://127.0.0.1:8000;
proxy_set_header 主机 $host;
proxy_set_header X-Real-IP $remote_addr;
}
这似乎工作正常,标题在那里(我在调试器中看到它)。
现在,我尝试跟随this solution here,使用请求包装和过滤器,但它不起作用,因为显然我的自定义包装请求对象不是 MVC 机制使用的对象。映射如下:
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter-mapping>
<filter-name>RealIPFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
我尝试在代码中的两个(不同)位置提取远程地址:
1)
public class PostAuthSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(
HttpServletRequest request,
HttpServletResponse response,
Authentication authentication)
throws IOException, ServletException {
// here
request.getRemoteAddr();
}
}
和
2)
public class LoginFailureEventListenter implements
ApplicationListener<AuthenticationFailureBadCredentialsEvent> {
@Override
public void onApplicationEvent(AuthenticationFailureBadCredentialsEvent event) {
String remoteIP = null;
Object src = event.getSource();
if(src instanceof UsernamePasswordAuthenticationToken) {
UsernamePasswordAuthenticationToken upat = (UsernamePasswordAuthenticationToken) src;
if(upat.getDetails() instanceof WebAuthenticationDetails) {
// here
remoteIP = ((WebAuthenticationDetails)upat.getDetails()).getRemoteAddress();
}
}
}
使用 Spring MVC 解决此问题的正确方法是什么?
编辑
由于应用程序受到 Spring 安全性的保护,这也可能仅与使 Spring 安全性接受包装的请求有关,或者将此过滤器应用为处理链中的第一个过滤器,或者达到这种效果(如果可能的话)。
【问题讨论】:
-
确保您的包装发生在弹簧安全之前。将包含 yuor wrapping filter 的 filter-mapping 元素移到 filter-mapping 之前,以确保 spring 安全。
-
是的,好像我用编辑回答了我自己的问题。刚刚试了一下,它可以工作
<custom-filter position="FIRST" ref="realIPFilter" />。既然您的建议似乎有效,您愿意给出一个我可以接受的答案吗? -
您的过滤器不必是 spring security 过滤器链的一部分,您可以简单地在 web.xml 中定义它并确保它在 spring security 的过滤器链之前执行。
-
我该怎么做(如何在 web.xml 中指定顺序)?如果这只是由xml文件中的顺序决定的,我试过了,还是不行……
-
更正 - 它有效。我一定是忘记重新启动服务器或做错了什么。
标签: java http tomcat spring-mvc nginx