java中防御sql注入的核心是使用preparedstatement参数化查询,而非依赖运行时异常检测;辅以输入白名单校验、数据库最小权限和waf作为纵深防御。

Java 中检测并拦截 SQL 注入攻击,核心在于**不依赖运行时抛出 SqlInjectionDetectedException 这类自定义异常来实现防护**——因为这不是标准做法,也容易误判或漏判。真正的防御应前置在编码和架构层面,而非靠事后“检测+抛异常”来兜底。
SQL 注入无法靠字符串扫描可靠识别
所谓“检测 SQL 注入”通常指对用户输入做关键词(如 union、select、;、')匹配,但这种方式极易绕过或误报。比如 Base64 编码、宽字节、注释符绕过、大小写混写等都可逃逸规则。直接抛 SqlInjectionDetectedException 看似主动,实则把安全责任推给了不可靠的文本分析。
正确做法:用预编译参数化查询(PreparedStatement)
这是最根本、最有效的防御方式。数据库驱动会将 SQL 结构与参数严格分离,参数值永远被当作数据处理,不会参与 SQL 解析。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 避免拼接 SQL 字符串:
"SELECT * FROM user WHERE name = '" + name + "'" - 改用 PreparedStatement:
SELECT * FROM user WHERE name = ?,再用setString(1, name) - JPA/Hibernate 用户应使用
@Param或命名参数,禁用原生 SQL 拼接 - MyBatis 中优先用
#{}(预编译),慎用${}(字符串替换)
补充防护:输入校验 + 最小权限 + WAF
参数化查询是基石,其他措施是纵深防御:
- 对输入做白名单校验(如手机号只允许数字、邮箱用标准正则)
- 数据库账号仅授予必要表的 CRUD 权限,禁用
SELECT ... INTO OUTFILE等高危操作 - 在网关或反向代理层部署 Web 应用防火墙(WAF),如 ModSecurity,用于识别常见注入模式(作为最后一道防线,非替代方案)
不建议自行实现“注入检测拦截器”
除非有强审计合规要求且能接受高误报率,否则不推荐在 Filter 或 AOP 中统一扫描请求参数并抛 SqlInjectionDetectedException。它既不能替代参数化查询,又可能阻断合法请求(如用户昵称含单引号、JSON 字段含 SQL 关键字等),反而损害可用性。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










