spring cloud gateway中读取请求体必须用flux非阻塞处理,禁用block();json需精准提取字符串值检测sql关键词;nginx需启用body解析并统一解码层级;sql检测须在验签通过后执行且限长限流。

Spring Cloud Gateway 中读取请求体必须用 Flux,不能用 block()
直接调用 exchange.getRequest().getBody().block() 会阻塞线程、拖垮网关吞吐量,压测时 TPS 断崖下跌。真实场景中应保持非阻塞流式处理:
- 对
application/json类型,用exchange.getRequest().getBody()获取Flux<databuffer></databuffer>,再flatMap拼接为DataBuffer - 用
DataBufferUtils.join()合并后转成byte[],再 UTF-8 解码为字符串 - 禁止在 GlobalFilter 中调用任何带
block()的方法——它会让 WebFlux 变成伪异步
JSON Body 必须递归扫描所有字符串字段,不能只 toString() 全文匹配
jsonNode.toString() 会把 {、:、" 等结构符一并纳入扫描,导致误报(比如把正常字段名 user_name 里的 user 当成 SQL 关键字)。正确做法是精准提取值:
- 用
ObjectMapper.readTree(byte[])加载为JsonNode - 遍历所有
JsonNodeType.STRING节点,或用jsonNode.findValuesAsText(".*")提取全部字符串值 - 对每个字符串值单独做关键词检测:
'、;、--、#、UNION、SELECT、EXEC(忽略大小写)
Nginx 网关只能拦 query 和 path,POST body 需额外模块且必须解码一致
纯 Nginx 的 $args 和 $request_uri 不含 POST body,if ($args ~* union) { return 403; } 对 JSON 请求完全无效。要覆盖 body,必须:
- 启用
ModSecurity或ngx_http_body_filter_module,并设置SecRequestBodyAccess On - 配置
client_body_buffer_size 1m,防大文件耗尽内存 - 确保解码层级一致:Nginx 要至少解一层 URL 编码(如
%27→'),否则%27OR%201%3D1直接放行 - 攻击者常发双重编码(如
%2555NION),Nginx 需配合rewrite ^(.*)$ $1 break;+set $args重写参数,让规则作用于最终解码结果
SQL 检测必须放在验签之后,且需限制扫描长度
未校验签名就扫描请求体,等于给攻击者免费提供 CPU 和内存资源——恶意构造超长 base64 字段可触发 OOM。真实部署中必须:
- 先从 header 或 query 提取
appKey,查配置中心获取对应appSecret - 校验
timestamp(≤ 5 分钟)、nonce(Redis 去重)、签名原文(字典序拼接) - 验签通过后,才对请求体做 SQL 特征扫描;且强制限制最大扫描长度(如 ≤ 1MB),超长直接拒
- 关键词规则不能只靠正则匹配简单词,必须叠加限流:
limit_req_zone $binary_remote_addr zone=sql_att:10m rate=1r/s,高频触发即封 IP
实际拦截逻辑最易被忽略的点,是「解码顺序」和「执行顺序」:Nginx 与后端对同一段 URL 的解码层数不同,会导致规则失效;验签与 SQL 检测顺序颠倒,会让防御变成 DoS 工具。这两处不校准,再多的关键词规则也形同虚设。











