Spring Cloud Gateway 必须先验签再扫描 body,否则规则形同虚设:需先从 header 或 query 提取 appKey 查配置中心获取 appSecret,按字典序拼接 timestamp 和 nonce 验签,超时或 nonce 重复即拒;验签通过后才缓存并递归遍历 JSON 字符串节点检测 SQL 注入。

Spring Cloud Gateway 必须先验签再扫描 body,否则规则形同虚设
验签失败就去扫 SQL 特征,等于把检测服务暴露给任意伪造的 appKey。攻击者发个 appKey=abc×tamp=123&nonce=xyz,网关还没查配置中心拿 appSecret 就直接进 JsonNode 递归扫描,既绕过身份约束,又可能因阻塞式读取 body.asString().block() 耗尽线程。
真实可行链路只有这一条:
- 从
exchange.getRequest().getHeaders().getFirst("appKey")或 query 中提取appKey - 查配置中心(如 Nacos/Apollo)拿到对应
appSecret - 用
timestamp和nonce按字典序拼接后验签,超时(>300000ms)或 Redis 已存在该nonce则直接拒 - 验签通过后,才调用
ServerWebExchangeUtils.cacheRequestBody+CacheBodyGlobalFilter获取可重复读的Flux<databuffer></databuffer>
JSON body 里的 SQL 注入字段必须递归遍历,不能 toString() 全文匹配
toString() 会把整个 JSON 树转成扁平字符串,丢失结构信息,且极易误报(比如字段名含 union、值里有 order by 注释)。真正要扫的是所有 JsonNodeType.STRING 类型的叶节点值。
示例代码关键片段:
jsonNode.traverse().forEachRemaining(node -> {
if (node.isTextual()) {
String value = node.textValue();
if (SQL_INJECTION_PATTERN.matcher(value).find()) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "SQL injection detected");
}
}
});注意三点:
- 必须用
node.textValue(),不是node.toString() - 正则需支持常见绕过:如
%27OR%201%3D1(URL 解码后匹配)、/**/UNION/**/SELECT(空白符/注释干扰) - 深度限制建议设为 10 层,防恶意构造超深嵌套 JSON 导致栈溢出
Nginx 网关对 POST body 完全不可见,除非显式启用 ModSecurity
if ($args ~* union) 这类规则只作用于 query string,对 application/json 请求体里的 "name": "admin'--" 完全无效。Nginx 默认不解析 POST body,必须手动启用 ModSecurity 并打开请求体访问开关。
关键配置项(必须放在 location 块内,不能放 http 或 server 顶层):
-
SecRequestBodyAccess On—— 否则REQUEST_BODY变量为空 -
SecResponseBodyAccess Off—— 避免响应体误触发规则干扰判断 -
SecRequestBodyLimit 1048576—— 控制最大解析体积,防 OOM - 所有规则必须写在
location /api { ... }内,否则 Nginx 启动报错
东西向调用(service-to-service)根本不会经过边缘网关,得靠 Envoy Sidecar
用户请求走 Spring Cloud Gateway 是南北向,但 user-service → order-service 这类内部调用完全不经过它。此时唯一能拦住 SQL 注入的,是部署在每个 Pod 里的 Envoy Sidecar。
Sidecar 默认不读 body,必须显式配置:
- 在
http_connection_manager的路由中添加per_route_config+ext_authz过滤器 - 设置
with_request_body: { max_request_bytes: 1048576 },否则ext_authz收不到完整 payload - 推荐将可疑请求转发给独立的 SQL 解析服务(如基于
libinjection的轻量级解析器),而非在 Envoy 内做正则匹配——性能差且规则难维护
最易被忽略的一点:gRPC gateway 把 JSON 转成 protobuf 后透传,若网关没解析原始 JSON,UNIO 这类截断关键词根本看不到。必须确保解析发生在协议转换之前。

















