You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Api-Gateway的CustomGlobalFilter过滤网关自身Controller请求?

问题根源

Spring Cloud Gateway 的 GlobalFilter 仅作用于网关路由转发的请求,而网关自身的 @Controller/@RestController 请求是由 Spring MVC/WebFlux 的核心调度器直接处理,不会进入 Gateway 的过滤链路,因此调整 @Order 或添加路由配置无法覆盖这类请求。

解决方案

方案1:将网关自身接口配置为路由转发到自身

把网关作为服务注册到注册中心,然后添加路由规则,让前端请求网关自身接口时走 Gateway 过滤链。

示例配置(application.yml):

spring:
  cloud:
    gateway:
      routes:
        # 原有业务服务路由
        - id: other-service-route
          uri: lb://other-service
          predicates:
            - Path=/api/service/**
        # 网关自身接口的路由(指向网关服务名)
        - id: gateway-self-route
          uri: lb://api-gateway-service # 替换为你的网关服务注册名
          predicates:
            - Path=/api/gateway/** # 网关自身Controller的接口路径

此方案下,所有请求(包括网关自身接口)都会经过 GlobalFilter 处理,但需要确保网关已注册到服务发现组件(如Nacos/Eureka)。

方案2:复用过滤逻辑,分别实现 Gateway Filter 和 MVC/WebFlux 拦截器

将核心过滤逻辑抽离为公共类,同时适配 Gateway 的 GlobalFilter 和网关自身Controller的拦截器(MVC用HandlerInterceptor,WebFlux用WebFilter)。

步骤1:抽离公共过滤逻辑

@Component
public class CommonFilterHandler {
    /**
     * 公共过滤逻辑:返回true表示通过,false表示拦截
     */
    public boolean processFilter(HttpServletRequest request, HttpServletResponse response) {
        // 示例:校验请求头Token
        String token = request.getHeader("Authorization");
        if (token == null || !token.startsWith("Bearer ")) {
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            return false;
        }
        // 其他过滤逻辑:日志、参数校验等
        return true;
    }
}

步骤2:实现 Gateway GlobalFilter

@Component
public class CustomGlobalFilter implements GlobalFilter, Ordered {
    @Autowired
    private CommonFilterHandler commonFilterHandler;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        HttpServletRequest request = exchange.getRequest().getNativeRequest(HttpServletRequest.class);
        HttpServletResponse response = exchange.getResponse().getNativeResponse(HttpServletResponse.class);

        boolean pass = commonFilterHandler.processFilter(request, response);
        if (!pass) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return -100; // 调整顺序,确保在核心过滤逻辑前执行
    }
}

步骤3:适配网关自身Controller的拦截器

如果网关用的是Spring MVC:

// 1. 实现HandlerInterceptor
@Component
public class CustomMvcInterceptor implements HandlerInterceptor {
    @Autowired
    private CommonFilterHandler commonFilterHandler;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return commonFilterHandler.processFilter(request, response);
    }
}

// 2. 注册拦截器
@Configuration
public class MvcInterceptorConfig implements WebMvcConfigurer {
    @Autowired
    private CustomMvcInterceptor customMvcInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(customMvcInterceptor)
                .addPathPatterns("/api/gateway/**"); // 网关自身接口路径
    }
}

如果网关用的是Spring WebFlux(Gateway默认依赖WebFlux):

@Component
public class CustomWebFilter implements WebFilter, Ordered {
    @Autowired
    private CommonFilterHandler commonFilterHandler;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        HttpServletRequest request = exchange.getRequest().getNativeRequest(HttpServletRequest.class);
        HttpServletResponse response = exchange.getResponse().getNativeResponse(HttpServletResponse.class);

        boolean pass = commonFilterHandler.processFilter(request, response);
        if (!pass) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return -100; // 调整优先级
    }
}

此方案无需修改请求路径,同时覆盖路由转发和网关自身接口的过滤需求。

方案3:使用WebFilter统一处理(仅适用于WebFlux网关)

如果网关基于WebFlux(Spring Cloud Gateway默认如此),直接实现 WebFilter 即可覆盖所有WebFlux处理的请求,包括路由转发和网关自身Controller的请求,无需额外配置 GlobalFilter。

示例代码:

@Component
public class UnifiedWebFilter implements WebFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        // 过滤逻辑示例:记录请求日志
        String path = exchange.getRequest().getPath().toString();
        System.out.println("Received request: " + path);

        // 其他逻辑:鉴权、参数校验等
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return -100; // 确保优先级高于默认过滤器
    }
}

内容的提问来源于stack exchange,提问作者vikiJ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 02:20:54