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

时间:2017-08-21 16:19:50

标签: spring-boot tomcat8 netflix-zuul spring-cloud-netflix

我使用此配置启用基于Spring Boot的微服务环境 -

  1. nginx作为centos 7上的负载均衡器。(配置为使用x-forwarded-for)
  2. 基于netflix zuul代理服务器的Spring启动API网关。 Tomcat是嵌入式容器。
  3. 基于Spring Cloud的产品微服务。 Tomcat作为嵌入式容器。
  4. Spring Boot版本:1.5.6

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

    现在,当我想在产品Microservice中获取远程客户端IP地址时出现问题。我总是得到127.0.0.1作为IP地址。以下是产品微服务中提取客户端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

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

1 个答案:

答案 0 :(得分: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();
    }
}