Gateway 网关统一鉴权拦截器放行路径配置失效为什么?

文章导读
大多数情况下,这是因为路径匹配规则与请求实际 URI 不一致,或者鉴权过滤器的执行顺序早于放行逻辑。
📋 目录
  1. 核心原因分析
  2. Spring Cloud Gateway 解决方案
  3. Kong/APISIX 配置参考
  4. 验证与排查
  5. 常见坑
A A

大多数情况下,这是因为路径匹配规则与请求实际 URI 不一致,或者鉴权过滤器的执行顺序早于放行逻辑。

先说结论:配置失效通常不是代码错误,而是匹配模式或执行优先级问题,需优先检查路径语法和过滤器顺序。

  • 先确认:放行路径使用的是 Ant 风格还是正则,是否包含上下文路径。
  • 先处理:调整鉴权过滤器 Order 值,确保放行判断逻辑优先执行。
  • 再验证:通过日志观察请求是否命中放行规则,再测试接口访问。

核心原因分析

网关鉴权通常是通过过滤器链(Filter Chain)实现的。请求进来后,会依次经过多个过滤器。如果鉴权过滤器的执行顺序排在放行判断之前,那么即使配置了放行路径,请求也会先被鉴权逻辑拦截。

另外,路径匹配机制也存在差异。Spring Cloud Gateway 默认使用 PathPatternParser,支持 *** 通配符。如果配置的是 /api/public/* 但实际请求是 /api/public/user/info,单层星号无法匹配多层路径。此外,URL 编码也可能导致匹配失败,例如空格被编码为 %20,而配置中写的是空格。

推荐优先使用 Ant 风格路径匹配,在配置一致性上比正则更容易维护。

Spring Cloud Gateway 解决方案

以下是基于 Spring Cloud Gateway 的标准排查与修复步骤,包含配置绑定与过滤器实现。

第一步:核对路径匹配模式与配置绑定

检查配置文件中的放行路径。自定义白名单配置需要代码支持才能生效,以下是标准的 YAML 配置与 Java 绑定示例:

# application.yml 配置示例
custom:
  auth:
    skip-paths:
      - /api/public/**
      - /health/**

在代码中通过 @ConfigurationProperties@Value 读取该配置,确保配置键与代码一致:

@Component
public class AuthFilter implements GlobalFilter, Ordered {

    // 读取配置中的白名单路径
    @Value("${custom.auth.skip-paths}")
    private List<String> skipPaths;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String path = exchange.getRequest().getPath().value();
        // 匹配逻辑
        if (skipPaths.stream().anyMatch(pattern -> new AntPathMatcher().match(pattern, path))) {
            return chain.filter(exchange); // 放行
        }
        // 继续鉴权逻辑...
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        // 数值越小优先级越高,需确保小于实际鉴权逻辑的 Order
        // 避免使用 -1,防止与 NettyWriteResponseFilter 等系统过滤器冲突
        return -100; 
    }
}

第二步:调整过滤器顺序

如果是自定义代码实现的鉴权过滤器,检查 @Order 注解或 getOrder() 方法返回值。放行逻辑应该在鉴权逻辑之前执行。

注意:硬编码 -1 可能与框架内置过滤器(如 NettyWriteResponseFilter)冲突。建议定义常量管理顺序,例如 AuthOrder.WHITE_LIST = -100AuthOrder.AUTH_CHECK = 0

第三步:检查 URL 编码影响

部分网关在匹配前会对 URI 进行解码,部分则不会。如果配置中包含特殊字符,建议统一使用解码后的路径进行配置,并在测试时使用浏览器直接访问而非 curl 编码后的地址。

Kong/APISIX 配置参考

如果您使用的是 Kong 或 APISIX,配置方式与 Spring Cloud Gateway 不同,需检查 Plugin 的执行优先级。

Kong 配置示例:

# 启用 key-auth 插件并配置白名单
curl -X POST http://kong:8001/services/{service}/plugins \
  `--data` "name=key-auth" \
  `--data` "config.key_names=apikey" \
  `--data` "config.hide_credentials=true"

在 Kong 中,需通过 config.skip_consumer 或前置插件逻辑实现放行,具体取决于使用的鉴权插件版本。

Gateway 网关统一鉴权拦截器放行路径配置失效为什么?

APISIX 配置示例:

# 在路由配置中设置 plugin_attr 或使用 consumer 插件
{
  "uri": "/api/public/*",
  "plugins": {
    "key-auth": { "disable": true }
  }
}

验证与排查

1. 日志观察

开启网关应用的 DEBUG 级别日志,重点关注过滤器链的执行记录。寻找类似 Skipping auth for pathMatched whitelist 的日志输出。如果没有看到放行日志却看到了鉴权失败日志,说明匹配未生效。

2. curl 测试

使用 curl 命令访问放行路径,观察返回状态码。预期应该是 200 或直接透传到后端,而不是 401/403。

curl -v http://gateway-host/api/public/test

如果返回 401,说明鉴权拦截依然生效。

3. 后端验证

在后端服务中打印请求头。如果鉴权生效,通常会有特定的 Token 头;如果放行,可能没有 Token 头但请求依然到达后端。确认后端是否收到了请求。

常见坑

1. 末尾斜杠问题

配置 /api/public 时,请求 /api/public/ 可能被视为不同路径。建议在配置中统一是否包含末尾斜杠,或在网关层开启忽略末尾斜杠的配置。

2. 配置热更新未生效

如果使用了配置中心(如 Nacos、Apollo),修改放行路径后需确认配置是否已推送并刷新。部分网关过滤器在启动时加载配置,运行时修改可能不生效,需要重启服务。

3. 大小写敏感

路径匹配默认通常是大小写敏感的。配置 /API/public 无法匹配 /api/public。确保配置与请求路径的大小写完全一致。

4. 多过滤器冲突

如果网关中引入了多个安全相关插件(如 CORS 插件、限流插件、鉴权插件),它们之间可能存在顺序冲突。确保放行逻辑在所有安全拦截之前执行。