API网关是SQL注入第一道防线,因其能前置校验所有请求、统一管控微服务、覆盖非JSON接口,并与签名验证联动实现溯源告警。

移动端 App 的 SQL 注入风险,不能只靠客户端过滤或后端 ORM 框架“自动防护”——攻击者可绕过 App 直接发请求,SQL注入漏洞若未在网关层拦截,就等于把数据库裸露在公网。
为什么 API 网关是 SQL 注入的第一道防线
App 发出的每个请求都必须经过网关,而网关在路由转发前就能解析、校验、改写甚至阻断请求。相比业务服务层的 PreparedStatement,网关层拦截能:
- 提前拒绝含
UNION SELECT、' OR '1'='1、/*等特征的请求,不触达后端服务 - 统一管控所有微服务,避免某服务漏配参数化查询导致全链路失守
- 对非 JSON 请求(如表单提交、URL 查询参数)同样生效,覆盖
GET类搜索接口等高危场景 - 与签名验证联动:若签名合法但参数含恶意 SQL 片段,说明密钥已泄露或客户端被劫持,需立即告警
Spring Cloud Gateway 中嵌入 SQL 注入检测逻辑
Spring Cloud Gateway 默认不带 SQL 注入识别能力,需自定义 GlobalFilter 扫描请求体和查询参数。关键点不是“匹配全部变体”,而是聚焦高频攻击模式:
- 检查
request.getQueryParams()和ServerWebExchange.getFormData()中每个值是否含以下子串:'、"、;、--、#、UNION、SELECT、INSERT、EXEC(忽略大小写) - 对 JSON Body,用
Flux<databuffer></databuffer>异步读取并解析为Map或JsonNode后遍历所有字符串字段 - 命中规则时返回
400 Bad Request并记录原始参数(用于溯源),**不抛异常、不打印堆栈**,防止信息泄露 - 注意:正则匹配
OR\s+'1'\s*=\s*'1'类布尔盲注特征时,需用Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE
签名验证必须绑定时间戳与随机串,且不可绕过
网关层的 SignUtil.verify() 若只校验 sign 参数,攻击者可重放旧请求。真实场景中必须强制要求:
-
timestamp参数存在且为 long 类型,与当前时间差 ≤ 300000(5 分钟),超时即拒 -
nonce(随机串)参数长度 ≥ 8,且网关内存/Redis 中缓存最近 5 分钟内出现过的nonce,重复即拒 - 签名原文必须包含
timestamp和nonce,且二者参与排序拼接 —— 否则攻击者可固定 nonce + 修改 timestamp 绕过时效校验 - APP_SECRET 不得出现在请求头或 URL 中;网关通过
appKey查配置中心或数据库获取对应appSecret,避免硬编码
签名与 SQL 检测必须串联,不能独立启用
单独开签名或单独开 SQL 检测都会留下缺口:
- 只做签名:攻击者用合法 App 发送
keyword=xxx%27%20UNION%20SELECT%20...,签名仍有效 - 只做 SQL 检测:伪造请求去掉
sign参数,直接触发网关拦截,但无法区分是爬虫还是恶意调用 - 正确做法:先验签 → 签名通过后再执行 SQL 特征扫描 → 任一失败即中断。这样既能追溯来源(谁的 appKey),又能定位攻击手法(哪类 payload)
- 注意:
verify()方法里不要做耗时操作(如远程查 Redis),否则网关吞吐量暴跌;nonce去重建议用布隆过滤器 + 短期 TTL 的本地缓存
最易被忽略的是:网关日志里记录被拦截的 sign 值和原始参数时,必须脱敏处理 password、token、id_card 等字段 —— 否则日志本身就成了新的敏感信息泄露面。

















