Appearance
RemoveJsonAttributesResponseBody 网关过滤器工厂
概述
RemoveJsonAttributesResponseBody 是 Spring Cloud Gateway 提供的一个内置过滤器工厂,专门用于处理 JSON 响应体的属性移除。它允许开发者在网关层面对下游服务返回的 JSON 数据进行清理和过滤,移除敏感或不必要的字段。
功能特性
IMPORTANT
该过滤器主要解决了在微服务架构中,需要对下游服务返回的 JSON 响应进行字段过滤的问题,避免敏感信息暴露给客户端。
核心能力
- 属性移除:根据指定的属性名称列表移除 JSON 中的字段
- 层级控制:支持仅在根级别移除或递归移除所有层级的指定属性
- 灵活配置:通过简单的 YAML 配置即可实现复杂的 JSON 转换
业务场景
在实际的微服务开发中,RemoveJsonAttributesResponseBody 过滤器常用于以下场景:
1. 数据脱敏场景
当用户服务返回用户信息时,需要移除敏感字段如密码、内部 ID 等:
2. API 版本兼容
不同版本的客户端可能需要不同的数据结构,通过过滤器移除新版本字段:
配置参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| attribute names | String[] | 是 | 要移除的属性名称列表 |
| recursive | Boolean | 否 | 是否递归移除,默认 false(仅根级别) |
配置示例
基础配置 - 根级别移除
仅移除 JSON 根级别的指定属性:
yaml
spring:
cloud:
gateway:
routes:
- id: user_profile_route
uri: http://user-service
predicates:
- Path=/api/user/**
filters:
# 移除根级别的 password 和 internalId 字段
- RemoveJsonAttributesResponseBody=password,internalIdkotlin
@Configuration
class GatewayConfig {
@Bean
fun userProfileRoute(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
.route("user_profile_route") { r ->
r.path("/api/user/**")
.filters { f ->
f.filter(RemoveJsonAttributesResponseBodyGatewayFilterFactory()
.apply(RemoveJsonAttributesResponseBodyGatewayFilterFactory.Config()
.apply {
// 设置要移除的属性名称
attributeNames = listOf("password", "internalId")
// 仅在根级别移除 (默认值)
deleteRecursively = false
}))
}
.uri("http://user-service")
}
.build()
}
}处理效果演示
原始 JSON 响应:
json
{
"id": 1001,
"username": "zhangsan",
"password": "encrypted_password_hash",
"email": "zhangsan@example.com",
"internalId": "internal_user_12345",
"profile": {
"nickname": "张三",
"avatar": "https://example.com/avatar.jpg"
}
}过滤后的响应:
json
{
"id": 1001,
"username": "zhangsan",
"email": "zhangsan@example.com",
"profile": {
"nickname": "张三",
"avatar": "https://example.com/avatar.jpg"
}
}高级配置 - 递归移除
递归移除 JSON 中所有层级的指定属性:
yaml
spring:
cloud:
gateway:
routes:
- id: product_catalog_route
uri: http://product-service
predicates:
- Path=/api/products/**
filters:
# 递归移除所有层级的 cost 和 supplierId 字段
- RemoveJsonAttributesResponseBody=cost,supplierId,truekotlin
@Configuration
class ProductGatewayConfig {
@Bean
fun productCatalogRoute(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
.route("product_catalog_route") { r ->
r.path("/api/products/**")
.filters { f ->
f.filter(RemoveJsonAttributesResponseBodyGatewayFilterFactory()
.apply(RemoveJsonAttributesResponseBodyGatewayFilterFactory.Config()
.apply {
// 设置要移除的属性名称
attributeNames = listOf("cost", "supplierId")
// 递归移除所有层级
deleteRecursively = true
}))
}
.uri("http://product-service")
}
.build()
}
}递归处理效果演示
原始 JSON 响应:
json
{
"id": 2001,
"name": "智能手机",
"price": 2999.0,
"cost": 1800.0,
"supplierId": "SUPPLIER_001",
"variants": [
{
"id": 2001001,
"color": "黑色",
"storage": "128GB",
"cost": 1750.0,
"supplierId": "SUPPLIER_001"
},
{
"id": 2001002,
"color": "白色",
"storage": "256GB",
"cost": 1850.0,
"supplierId": "SUPPLIER_002"
}
]
}递归过滤后的响应:
json
{
"id": 2001,
"name": "智能手机",
"price": 2999.0,
"variants": [
{
"id": 2001001,
"color": "黑色",
"storage": "128GB"
},
{
"id": 2001002,
"color": "白色",
"storage": "256GB"
}
]
}实际业务应用案例
案例 1:电商平台商品信息过滤
在电商平台中,商品服务可能包含成本价格、供应商信息等内部数据,这些信息不应该暴露给前端客户:
kotlin
@Configuration
class ECommerceGatewayConfig {
@Bean
fun ecommerceRoutes(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
// 商品列表路由 - 移除成本相关信息
.route("product_list") { r ->
r.path("/api/v1/products")
.filters { f ->
f.removeJsonAttributesResponseBody("cost", "supplierPrice", "margin", true)
}
.uri("http://product-service")
}
// 用户信息路由 - 移除敏感信息
.route("user_info") { r ->
r.path("/api/v1/user/profile")
.filters { f ->
f.removeJsonAttributesResponseBody("password", "salt", "internalNotes")
}
.uri("http://user-service")
}
.build()
}
}案例 2:多租户 SaaS 平台数据隔离
在多租户环境中,需要根据租户权限过滤不同的数据字段:
kotlin
@Component
class TenantDataFilterConfig {
@Bean
fun tenantSpecificRoutes(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
// 基础租户 - 移除高级功能字段
.route("basic_tenant") { r ->
r.path("/api/data/**")
.and().header("X-Tenant-Type", "BASIC")
.filters { f ->
f.removeJsonAttributesResponseBody(
"advancedAnalytics",
"premiumFeatures",
"customReports",
true
)
}
.uri("http://data-service")
}
// 高级租户 - 保留所有字段
.route("premium_tenant") { r ->
r.path("/api/data/**")
.and().header("X-Tenant-Type", "PREMIUM")
.uri("http://data-service")
}
.build()
}
}工作原理
性能考虑
WARNING
使用该过滤器会增加网关的响应处理时间,因为需要解析和重新序列化 JSON 内容。
性能优化建议
- 合理使用递归模式:仅在必要时使用递归移除,根级别移除性能更好
- 控制 JSON 大小:对于大型 JSON 响应,考虑在服务端进行字段筛选
- 缓存策略:对于静态或变化较少的响应,可以结合缓存过滤器使用
注意事项
TIP
该过滤器只能处理有效的 JSON 格式响应体,对于非 JSON 内容会跳过处理。
CAUTION
移除属性操作是不可逆的,请确保移除的字段确实不被客户端需要。
最佳实践
- 明确字段用途:在移除字段前,确认这些字段不会被前端或下游系统使用
- 版本兼容性:考虑 API 版本兼容性,避免破坏现有客户端
- 监控和日志:添加适当的监控来跟踪过滤器的使用情况
- 测试覆盖:编写充分的测试来验证过滤器的行为
与其他过滤器的组合使用
RemoveJsonAttributesResponseBody 可以与其他网关过滤器组合使用,实现更复杂的功能:
kotlin
@Configuration
class CompositeFilterConfig {
@Bean
fun secureApiRoute(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
.route("secure_api") { r ->
r.path("/api/secure/**")
.filters { f ->
f.requestRateLimiter { config ->
// 限流配置
config.rateLimiter = redisRateLimiter()
config.keyResolver = ipKeyResolver()
}
.addRequestHeader("X-Gateway-Filter", "Applied")
.removeJsonAttributesResponseBody("internalId", "debug", true)
.addResponseHeader("X-Filtered", "true")
}
.uri("http://secure-service")
}
.build()
}
}通过合理使用 RemoveJsonAttributesResponseBody 过滤器,可以在网关层面实现有效的数据脱敏和字段过滤,提高 API 的安全性和数据传输效率。