使用Zuul网关过滤入站请求

问题描述

我有一个使用Zuul的网关服务。我只允许通过此网关来自特定host/origin/url的入站请求。我可以在网关服务的yaml文件(特别是 zuul 字段下)中设置一个属性来完成此操作吗?我的网关服务yaml看起来像这样:

description: the gateway service of the year
version: 1.0.0

server:
  port: 5555

spring:
  application:
    name: gateway-srv
  main:
    allow-bean-deFinition-overriding: true

homeUrl: http://localhost:8080  
    
zuul:
  routes:
    foo:
      authorization:
        password: baz
        username: bar
      path: /foo/**
      sensitiveHeaders: Cookie,Set-Cookie
      url: ${homeUrl}/lc

解决方法

您可以包含Zuul预过滤器来管理这种情况,类似于:

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import lombok.extern.log4j.Log4j2;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

import java.util.Optional;

import static java.util.Optional.ofNullable;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.DEBUG_FILTER_ORDER;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;

@Log4j2
@Component
public class RequestFilter extends ZuulFilter {

  @Override
  public String filterType() {
    return PRE_TYPE;
  }

  @Override
  public int filterOrder() {
    return DEBUG_FILTER_ORDER;
  }

  @Override
  public boolean shouldFilter() {
    return true;
  }

  @Override
  public Object run() {
    RequestContext ctx = RequestContext.getCurrentContext();
    log.info(getRequestInformation(ctx.getRequest()));

    return getRequestInformation(ctx.getRequest())
            .filter(rInfo -> !allowedRequest(rInfo))
            .map(rInfo -> {

              // You can adapt it,usign for example,a Json as response
              ctx.setResponseBody("Request not authorized");
              ctx.setSendZuulResponse(false);
              ctx.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
              return ctx;
            })
            .orElse( null);
  }


  private boolean allowedRequest(RequestInformation requestInformation) {
    // Include here what you need to verify
    // Modify with the suitable result
    return false;
  }


  private Optional<RequestInformation> getRequestInformation(HttpServletRequest httpRequest) {
    return ofNullable(httpRequest)
            .map(req -> {
                String hostAndPort = req.getHeader("host");
                return new RequestInformation(
                        httpRequest.getRequestURI(),ofNullable(hostAndPort).map(hp -> hp.substring(0,hp.indexOf(":"))).orElse(null),ofNullable(hostAndPort).map(hp -> Integer.valueOf(hp.substring(hp.indexOf(":")+1))).orElse(null));
            });
  }

  // Dummy class to include the information you need to check
  class RequestInformation {
    private String url;
    private String host;
    private Integer port;

    public RequestInformation(String url,String host,Integer port) {
        this.url = url;
        this.host = host;
        this.port = port;
    }
    public String getUrl() {
        return url;
    }
    public String getHost() {
        return host;
    }
    public Integer getPort() {
        return port;
    }

    @Override
    public String toString() {
        return "RequestInformation{" +
                "url='" + url + '\'' +
                ",host='" + host + '\'' +
                ",port=" + port +
                '}';
    }
  }
}

现在,如果您基于Zuul运行网关服务,则应该在日志中看到:

RequestInformation information

而且,如果您保持allowedRequest返回一个false值:

Unauthorized in Zuul filter