应在模型绑定后、控制器执行前拦截注入,通过运行时参数驱动的条件化验证器实现动态校验;结合参数化查询、错误页关闭及日志审计形成多层防护。

直接在接口层拦截黑客数据注入,关键不是等异常发生再处理,而是把验证做在请求进入业务逻辑之前——用运行时可变的参数 + 条件化验证器,实现动态、精准、可配置的拦截。
明确验证时机:别等异常抛出才响应
运行时异常(比如 SqlException 或 HttpRequestValidationException)是防御失败后的“警报”,不是防线本身。真正有效的拦截必须发生在模型绑定之后、控制器方法执行之前。这时请求参数已解析为对象,但业务逻辑尚未触发,是插入验证逻辑的黄金窗口。
- ASP.NET Core 中,在 Minimal API 里用
Validator.TryValidateObject手动校验;在 Controller 中启用[ApiController]特性,框架会自动对[FromBody]和[FromQuery]参数执行注解验证并返回 400 - Spring Boot 中,配合
@Valid+@ControllerAdvice全局异常处理器,让校验失败统一走MethodArgumentNotValidException分支,不暴露堆栈或数据库细节 - 切忌在
catch (Exception e)里做注入判断——此时 SQL 可能已执行,敏感信息可能已泄露
用运行时参数驱动验证规则
黑客常根据接口行为试探规则(比如反复提交 ' OR '1'='1),所以验证不能写死。需结合当前请求上下文动态启用/调整规则:
- 按请求来源分级:来自内网 IP 的请求可跳过敏感词检测,公网请求则强制启用
sqlPattern正则扫描(如匹配union select、exec xp_cmdshell) - 按用户权限控制强度:普通用户提交的
remark字段只校验长度和基础字符集;管理员提交的script字段则启用 AST 解析级校验,拒绝任何含函数调用的 JS 表达式 - 按接口路径差异化:
/api/v1/user/search对keyword参数启用模糊匹配白名单(仅允许中文、字母、空格);而/api/v1/report/export则额外检查该参数是否出现在 SQL 的WHERE子句模拟环境中
条件验证器设计要点
所谓“条件验证器”,是指验证逻辑本身可开关、可组合、可嵌套,而不是一个固定 if-else 块:
- 推荐使用 FluentValidation(.NET)或 Custom Validator + @Validated(Spring)替代纯 Data Annotations,便于写
When(x => x.IsAdmin, () => RuleFor(x => x.Script).Must(BeSafeScript))这类条件规则 - 验证器内部避免硬编码黑名单。例如检测 SQL 注入,不要只比对几个关键字,而应解析 token 流:将输入按空格/括号切分后,检查是否存在连续的
SELECT+FROM+ 非白名单表名结构 - 对高危字段(如
redirect_url、callback)强制要求 协议+域名白名单校验,而非简单过滤javascript:—— 黑客会用data:text/html;base64,...或vbscript:绕过
配套防护不可少
单靠参数验证无法完全堵住注入漏洞,必须与底层机制协同:
- 永远使用参数化查询:验证只是第一道筛子,DB 层必须杜绝拼接 SQL。即使验证漏掉一个单引号,参数化也能让它变成普通字符
-
关闭详细错误页:生产环境禁用
DeveloperExceptionPage(.NET)或spring.mvc.throw-exception-if-no-handler-found=true(Spring),防止泄露表结构、路径、框架版本 - 记录可疑请求元数据:对触发验证失败的请求,记录 User-Agent、X-Forwarded-For、原始 payload 的哈希(非明文)、匹配到的规则 ID,用于后续聚类分析攻击模式










