Tim*_*Tim 6 apache spring-security spring-cloud netflix-zuul
为了安全检查,我需要在我的资源服务中访问用户的远程IP地址.这个资源服务是一个简单的最新Spring Boot应用程序,它使用我的Eureka服务器注册自己:
@SpringBootApplication
@EnableEurekaClient
public class ServletInitializer extends SpringBootServletInitializer {
public static void main(final String[] args) {
SpringApplication.run(ServletInitializer.class, args);
}
}
Run Code Online (Sandbox Code Playgroud)
我尤里卡服务器注册的所有服务都通过基于Angel.SR3我Zuul路由代理服务器的动态路由starter-zuul和starter-eureka:
@SpringBootApplication
@EnableZuulProxy
@EnableEurekaClient
public class RoutingProxyServer {
public static void main(final String[] args) {
SpringApplication.run(RoutingProxyServer.class, args);
}
}
Run Code Online (Sandbox Code Playgroud)
Zuul路由代理服务器还为下一步配置AJP连接器:
@Configuration
@ConditionalOnProperty("ajp.port")
public class TomcatAjpConfig extends TomcatWebSocketContainerCustomizer {
@Value("${ajp.port}")
private int port;
@Override
public void doCustomize(final TomcatEmbeddedServletContainerFactory tomcat) {
super.doCustomize(tomcat);
// Listen for AJP requests
Connector ajp = new Connector("AJP/1.3");
ajp.setPort(port);
tomcat.addAdditionalTomcatConnectors(ajp);
}
}
Run Code Online (Sandbox Code Playgroud)
对动态路由zuul代理的所有请求都通过Apache代理,以便在标准443端口上提供HTTPS:
# Preserve Host when proxying so jar apps return working URLs in JSON responses
RequestHeader set X-Forwarded-Proto "https"
ProxyPreserveHost On
# Redirect remaining traffic to routing proxy server
ProxyPass / ajp://192.168.x.x:8009/
# Also update Location, Content-Location and URI headers on HTTP redirect responses
ProxyPassReverse / ajp://192.168.x.x:8009/
Run Code Online (Sandbox Code Playgroud)
有了这一切,资源服务就可用,但不幸的是,我从Spring Security获得的remoteAddress是Zuul代理/ Apache服务器的地址,而不是远程客户端IP地址.
在过去,我使用了一个org.springframework.security.authentication.AuthenticationDetailsSource优先于X-Forwarded-For正常的标头值remoteAddress来获取正确的IP地址,但是当我通过两个代理时,我无法知道如何将正确的远程IP地址传递给我的资源服务(Apache + Zuul) .
任何人都可以帮助我访问这两个代理背后的正确远程IP地址,或者建议一种替代方法来实现这一点吗?
原来,X-Forwarded-For标头是从原始请求中提取的,并送入Zuul进行填充HttpServletRequest#getRemoteAddr()。然后,这必须通过传递给代理后端服务RequestContext#getZuulRequestHeaders().put("X-Forwarded-For", remoteAddr)。ZuulFilter即使尚未将其自身的值附加到X-Forwarded-For过滤器中,也可以通过以下操作来实现。
@Component
@Slf4j
public class XForwardedForFilter extends ZuulFilter {
private static final String X_FORWARDED_FOR = "X-Forwarded-For";
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
// Rely on HttpServletRequest to retrieve the correct remote address from upstream X-Forwarded-For header
HttpServletRequest request = ctx.getRequest();
String remoteAddr = request.getRemoteAddr();
// Pass remote address downstream by setting X-Forwarded for header again on Zuul request
log.debug("Settings X-Forwarded-For to: {}", remoteAddr);
ctx.getZuulRequestHeaders().put(X_FORWARDED_FOR, remoteAddr);
return null;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 10000;
}
}
Run Code Online (Sandbox Code Playgroud)
可能需要在代理到Zuul之前清除Apache中的标头值,以防止仅接受用户提供的任何值: RequestHeader unset X-Forwarded-For
| 归档时间: |
|
| 查看次数: |
5085 次 |
| 最近记录: |