
[英]Request to an other service in a GlobalFilter in spring cloud gateway
[英]Spring Cloud Gateway Filter with external configuration service call
我正在开发一个 Spring Cloud Gateway 应用程序,它有一个过滤器,可以根据不同服务持有的配置控制对某些路径或功能的访问。 因此,如果路径与功能 x 关联,则仅当配置服务返回功能 x 已启用时才允许访问。
配置以 Mono 的形式返回,然后进行平面映射以检查启用的功能。 这一切似乎都正常工作。 如果启用该功能,则允许请求通过链进行。 如果禁用该功能,则响应状态设置为禁止,请求标记为完成。 然而,这似乎并没有停止过滤器链,请求继续被处理并最终返回 200 响应。
如果功能配置不是从外部源返回并且立即可用,则此逻辑可以正常工作,但这涉及阻塞调用并且似乎不可取。 我看不出第一种方法有什么问题。 它似乎类似于其他地方可用的示例。
这是我想这样做的方式:
override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono<Void> {
logger.info("Feature Security Filter")
// getFeatures returns Mono<Map<String, Boolean>>
return featureConfigService.getFeatures().flatMap { features ->
val path = exchange.request.path.toString()
val method = exchange.request.method.toString()
if (featureMappings.keys.any { it.matcher(path).matches() }) {
val pathIsRestricted = featureMappings
.filter { it.key.matcher(path).matches() }
.filter { features[it.value.requiresFeature] != true || !it.value.methodsAllowed.contains(method) }
.isNotEmpty()
if (pathIsRestricted) {
logger.warn("Access to path [$method|$path] restricted. ")
exchange.response.statusCode = HttpStatus.FORBIDDEN
exchange.response.setComplete()
// processing should stop here but continues through other filters
}
}
chain.filter(exchange);
}
}
这种方式可行,但涉及 featureService 中的阻塞调用。
override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono<Void> {
logger.info("Feature Security Filter")
// this call returns a Map<String, Boolean> instead of a Mono
val features = featureService.getFeatureConfig()
val path = exchange.request.path.toString()
val method = exchange.request.method.toString()
if (featureMappings.keys.any { it.matcher(path).matches() }) {
val pathIsRestricted = featureMappings
.filter { it.key.matcher(path).matches() }
.filter { features[it.value.requiresFeature] != true || !it.value.methodsAllowed.contains(method) }
.isNotEmpty()
if (pathIsRestricted) {
logger.warn("Access to path [$method|$path] restricted. ")
val response: ServerHttpResponse = exchange.response
response.statusCode = HttpStatus.FORBIDDEN;
return response.setComplete()
// this works as this request will complete here
}
}
return chain.filter(exchange)
}
当测试运行时,我可以看到路径被正确记录为受限,并且响应状态按预期设置为 HttpStatus.FORBIDDEN,但请求继续由链中稍后的过滤器处理,并最终返回 200 响应。
我试过返回 Mono.error 和 onErrorComplete 的变体,但我得到了相同的行为。 我是 Spring 云网关的新手,看不出我做错了什么
在做了一些测试之后,我发现即使设置高阶,过滤器也会在路由过滤器之后执行。 如果你需要在路由之前过滤请求,你可以使用WebFilter
。 这是一个基于您的要求的工作 Java 示例。
package com.test.test.filters;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
import java.util.Map;
@Configuration
@Slf4j
public class TestGlobalFilter implements WebFilter, Ordered {
private Mono<Map<String, Boolean>> test() {
return Mono.just(Map.of("test", Boolean.TRUE));
}
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
log.info("Feature Security Filter");
// getFeatures returns Mono<Map<String, Boolean>>
return test().flatMap(features -> {
final var isRestricted = features.get("test");
if (Boolean.TRUE.equals(isRestricted)) {
log.info("Feature Security stop");
exchange.getResponse().setStatusCode(HttpStatus. FORBIDDEN);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
});
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.