首页 文章

基于Tomcat的Zuul代理服务器不会转发正确的客户端IP地址(request.getRemoteAddr())来结束微服务

提问于
浏览
0

我使用这种配置设置基于Spring Boot的微服务环境 -

  • nginx作为centos 7上的负载均衡器 . (配置为使用x-forwarded-for)

  • 基于netflix zuul代理服务器的Spring启动API网关 . Tomcat是嵌入式容器 .

  • 基于Spring Cloud的产品微服务 . Tomcat作为嵌入式容器 .

Spring Boot版本:1.5.6

当最终用户打电话给Product Microservice时,它会通过Nginx - > Api网关 - >产品服务 .

现在,当我想在产品Microservice中获取远程客户端IP地址时问题就出现了 . 我总是得到127.0.0.1作为IP地址 . 以下是Products微服务中获取客户端IP的代码

private String getClientIP() {       
    String xfHeader = request.getRemoteAddr();
    if (StringUtils.isBlank(xfHeader) || xfHeader.equals("127.0.0.1")) {
        return request.getHeader("X-Forwarded-For");
    }
    return xfHeader.split(",")[0];
}

API网关application.properties配置为使用 server.use-forward-headers: true

附:当我尝试从我的api网关切换到tomcat,然后我开始在产品微服务中获取真正的客户端IP地址 . 因此问题出在我的API网关中的Tomcat配置中 .

1 回答

  • 0

    你可以创建zuul过滤器并像这样更改位置

    zuul:
      ignoreSecurityHeaders: false
      routes:
        app:
          path: /app/**
          sensitiveHeaders: 
          url: http://localhost:8082/app/
    server:
        compression:
            enabled: true
        port: 80
    

    并过滤

    package smartHomeWebsite;
    
    import java.util.Optional;
    
    import org.springframework.cloud.netflix.zuul.filters.Route;
    import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
    import org.springframework.stereotype.Component;
    import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
    import org.springframework.web.util.UrlPathHelper;
    
    import com.netflix.util.Pair;
    import com.netflix.zuul.ZuulFilter;
    import com.netflix.zuul.context.RequestContext;
    
    @Component
    public class LocationHeaderRewritingFilter extends ZuulFilter {
    
        private final UrlPathHelper urlPathHelper = new UrlPathHelper();
        private final RouteLocator routeLocator;
    
        public LocationHeaderRewritingFilter(RouteLocator routeLocator) {
            this.routeLocator = routeLocator;
        }
    
        @Override
        public String filterType() {
            return "post";
        }
    
        @Override
        public int filterOrder() {
            return 100;
        }
    
        public boolean shouldFilter() {
            return extractLocationHeader(RequestContext.getCurrentContext()).isPresent();
        }
    
        public Object run() {
            RequestContext ctx = RequestContext.getCurrentContext();
            Route route = routeLocator.getMatchingRoute(urlPathHelper.getPathWithinApplication(ctx.getRequest()));
            if (route != null) {
                Pair<String, String> lh = extractLocationHeader(ctx).get();
                lh.setSecond(lh.second().replace(route.getLocation(),
                        ServletUriComponentsBuilder.fromCurrentContextPath().path(route.getPrefix()).build().toUriString()));
            }
            return null;
        }
    
    
        private Optional<Pair<String, String>> extractLocationHeader(RequestContext ctx) {
    
            return ctx.getZuulResponseHeaders()
                    .stream()
                    .filter(p -> "Location".equals(p.first()))
                    .findFirst();
        }
    }
    

相关问题