【问题标题】:Filtering inbound requests with Zuul gateway使用 Zuul 网关过滤入站请求
【发布时间】:2021-01-01 15:57:43
【问题描述】:
我有一个使用 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
【问题讨论】:
标签:
java
spring
microservices
netflix-zuul
gateway
【解决方案1】:
您可以包含一个 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 运行网关服务,您应该会在日志中看到:
而且,如果您保持 allowedRequest 返回 false 值: