Skip to content

RemoveRequestParameter 网关过滤器工厂

概述

RemoveRequestParameter 网关过滤器工厂是 Spring Cloud Gateway 提供的一个内置过滤器,用于在请求转发到下游服务之前移除指定的查询参数。这个过滤器在需要清理或隐藏某些敏感查询参数时非常有用。

解决的问题

在微服务架构中,我们经常遇到以下场景需要移除请求参数:

  • 安全考虑:移除包含敏感信息的参数(如调试参数、内部标识等)
  • 参数清理:去除不需要传递给下游服务的临时参数
  • 接口适配:适配不同版本的 API,移除新版本不支持的参数
  • 性能优化:减少不必要的参数传输

实际业务场景

场景 1:移除调试参数

在生产环境中,我们经常需要移除开发和测试阶段使用的调试参数:

场景 2:移除内部标识参数

移除不应该暴露给下游服务的内部参数:

配置方式

YAML 配置

yaml
spring:
  cloud:
    gateway:
      routes:
        - id: remove_debug_params
          uri: https://api.example.com
          predicates:
            - Path=/api/**
          filters:
            # 移除单个参数
            - RemoveRequestParameter=debug

        - id: remove_multiple_params
          uri: https://api.example.com
          predicates:
            - Path=/api/users/**
          filters:
            # 移除多个参数(需要配置多个过滤器)
            - RemoveRequestParameter=debug
            - RemoveRequestParameter=trace
            - RemoveRequestParameter=internal

Java 配置方式

kotlin
import org.springframework.cloud.gateway.route.RouteLocator
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
class GatewayConfig {

    /**
     * 配置路由和过滤器
     * 演示如何使用 RemoveRequestParameter 过滤器
     */
    @Bean
    fun customRouteLocator(builder: RouteLocatorBuilder): RouteLocator {
        return builder.routes()
            // 移除调试参数的路由
            .route("remove_debug_route") { r ->
                r.path("/api/users/**")
                    .filters { f ->
                        f.removeRequestParameter("debug")    // 移除 debug 参数
                         .removeRequestParameter("trace")    // 移除 trace 参数
                         .removeRequestParameter("internal") // 移除 internal 参数
                    }
                    .uri("http://user-service")
            }
            // 移除版本参数的路由
            .route("remove_version_route") { r ->
                r.path("/api/orders/**")
                    .filters { f ->
                        f.removeRequestParameter("v")        // 移除版本参数
                         .removeRequestParameter("apiKey")   // 移除API密钥
                    }
                    .uri("http://order-service")
            }
            .build()
    }
}
java
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class GatewayConfig {

    /**
     * 配置路由和过滤器
     * 演示如何使用 RemoveRequestParameter 过滤器
     */
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
            // 移除调试参数的路由
            .route("remove_debug_route", r ->
                r.path("/api/users/**")
                    .filters(f -> f
                        .removeRequestParameter("debug")    // 移除 debug 参数
                        .removeRequestParameter("trace")    // 移除 trace 参数
                        .removeRequestParameter("internal") // 移除 internal 参数
                    )
                    .uri("http://user-service")
            )
            // 移除版本参数的路由
            .route("remove_version_route", r ->
                r.path("/api/orders/**")
                    .filters(f -> f
                        .removeRequestParameter("v")        // 移除版本参数
                        .removeRequestParameter("apiKey")   // 移除API密钥
                    )
                    .uri("http://order-service")
            )
            .build();
    }
}

高级用法

结合条件过滤器使用

kotlin
@Bean
fun advancedRouteLocator(builder: RouteLocatorBuilder): RouteLocator {
    return builder.routes()
        .route("conditional_remove") { r ->
            r.path("/api/**")
                .and()
                .header("Environment", "production")  // 只在生产环境移除调试参数
                .filters { f ->
                    f.removeRequestParameter("debug")
                     .removeRequestParameter("test")
                     .removeRequestParameter("mock")
                }
                .uri("http://backend-service")
        }
        .build()
}

自定义过滤器扩展

如果需要基于条件移除参数,可以创建自定义过滤器:

kotlin
import org.springframework.cloud.gateway.filter.GatewayFilter
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory
import org.springframework.stereotype.Component
import org.springframework.web.util.UriComponentsBuilder
import reactor.core.publisher.Mono

/**
 * 自定义参数移除过滤器
 * 支持基于条件移除参数
 */
@Component
class ConditionalRemoveParameterGatewayFilterFactory :
    AbstractGatewayFilterFactory<ConditionalRemoveParameterGatewayFilterFactory.Config>() {

    init {
        super.setConfigClass(Config::class.java)
    }

    override fun apply(config: Config): GatewayFilter {
        return GatewayFilter { exchange, chain ->
            val request = exchange.request
            val uri = request.uri

            // 检查是否满足移除条件
            val shouldRemove = when (config.condition) {
                "production" -> request.headers.getFirst("Environment") == "production"
                "internal" -> request.headers.containsKey("X-Internal-Request")
                else -> true
            }

            if (shouldRemove && uri.query?.contains("${config.parameterName}=") == true) {
                // 构建新的URI,移除指定参数
                val newUri = UriComponentsBuilder.fromUri(uri)
                    .replaceQueryParam(config.parameterName)  // 移除参数
                    .build()
                    .toUri()

                // 创建新的请求
                val newRequest = request.mutate()
                    .uri(newUri)
                    .build()

                val newExchange = exchange.mutate()
                    .request(newRequest)
                    .build()

                chain.filter(newExchange)
            } else {
                chain.filter(exchange)
            }
        }
    }

    /**
     * 配置类
     */
    data class Config(
        var parameterName: String = "",  // 要移除的参数名
        var condition: String = ""       // 移除条件
    )
}

使用示例

示例 1:电商平台 API 清理

yaml
spring:
  cloud:
    gateway:
      routes:
        # 商品查询API - 移除内部参数
        - id: product_api
          uri: http://product-service
          predicates:
            - Path=/api/products/**
          filters:
            - RemoveRequestParameter=adminToken # 移除管理员令牌
            - RemoveRequestParameter=debugMode # 移除调试模式
            - RemoveRequestParameter=cacheBypass # 移除缓存绕过参数

        # 用户API - 移除测试参数
        - id: user_api
          uri: http://user-service
          predicates:
            - Path=/api/users/**
          filters:
            - RemoveRequestParameter=testUser # 移除测试用户标识
            - RemoveRequestParameter=mockData # 移除模拟数据标识

示例 2:移动端 API 适配

kotlin
@Bean
fun mobileApiRoutes(builder: RouteLocatorBuilder): RouteLocator {
    return builder.routes()
        // 移动端API路由 - 清理客户端特定参数
        .route("mobile_api") { r ->
            r.path("/mobile/api/**")
                .and()
                .header("User-Agent", ".*Mobile.*")
                .filters { f ->
                    f.stripPrefix(1)  // 移除 /mobile 前缀
                     .removeRequestParameter("deviceId")      // 移除设备ID(隐私保护)
                     .removeRequestParameter("appVersion")    // 移除应用版本
                     .removeRequestParameter("platform")      // 移除平台信息
                }
                .uri("http://api-service")
        }
        .build()
}

工作原理

注意事项

使用 `RemoveRequestParameter` 过滤器时需要注意以下几点:

WARNING

参数名称精确匹配:过滤器只会移除完全匹配的参数名,区分大小写。

TIP

性能考虑:移除参数操作会重新构建 URI,在高并发场景下需要考虑性能影响。

CAUTION

参数依赖:确保移除的参数不会影响下游服务的正常功能。

最佳实践

  1. 分环境配置:在不同环境使用不同的参数移除策略
  2. 日志记录:记录被移除的参数,便于调试和审计
  3. 测试验证:充分测试参数移除对下游服务的影响
  4. 文档维护:维护清晰的参数移除规则文档

相关过滤器

  • RemoveRequestHeader:移除请求头
  • RemoveResponseHeader:移除响应头
  • AddRequestParameter:添加请求参数
  • ModifyRequestBody:修改请求体

总结

RemoveRequestParameter 过滤器是一个简单但实用的工具,主要用于:

安全增强:移除敏感或调试参数
接口清理:保持 API 的简洁性
版本适配:处理不同版本间的参数差异
隐私保护:避免暴露内部实现细节

通过合理使用这个过滤器,可以提高系统的安全性和可维护性,同时简化下游服务的参数处理逻辑。