Java预防SQL注入的具体实践方法
1. 强制使用 PreparedStatement(参数化查询)
原理:将 SQL 语句结构与用户输入数据分离,确保输入内容始终作为“数据”处理,而非可执行的代码。
正确示例:
String sql = "SELECT * FROM users WHERE username = ? AND password = ?"; try (Connection conn = dataSource.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, username); // 自动转义特殊字符(如 ' -> \') pstmt.setString(2, password); try (ResultSet rs = pstmt.executeQuery()) { // 处理结果 } }
错误做法(高危!):
// 直接拼接 SQL(存在注入风险!) String sql = "SELECT * FROM users WHERE username = '" + username + "'"; Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql);
2. 使用 ORM 框架(如 Hibernate/JPA)
ORM 框架会自动生成参数化查询,减少手写 SQL 的注入风险。
Hibernate 示例:
// 使用 Hibernate Criteria API CriteriaBuilder cb = session.getCriteriaBuilder(); CriteriaQuery<User> query = cb.createQuery(User.class); Root<User> root = query.from(User.class); query.where( cb.equal(root.get("username"), username), cb.equal(root.get("password"), password) ); User user = session.createQuery(query).uniqueResult();
HQL 参数化:
String hql = "FROM User WHERE username = :username"; Query<User> query = session.createQuery(hql, User.class); query.setParameter("username", username); User user = query.uniqueResult();
3. 输入验证与过滤
白名单校验:
// 校验用户名是否符合规则(仅允许字母、数字、下划线) if (!username.matches("^[a-zA-Z0-9_]{4,20}$")) { throw new IllegalArgumentException("Invalid username"); }
转义特殊字符(备用方案):
如果必须拼接 SQL(如动态表名),需严格过滤:
// 使用 Apache Commons Text 转义 String safeInput = StringEscapeUtils.escapeSql(input); // 仅适用于简单场景,不推荐依赖!
4. 避免动态拼接 SQL
高危场景:动态表名、列名等无法通过 PreparedStatement
参数化。
安全做法:使用白名单校验合法值:
// 动态表名校验(只允许预定义的合法表名) Set<String> validTables = Set.of("users", "products"); if (!validTables.contains(tableName)) { throw new IllegalArgumentException("Invalid table name"); } String sql = "SELECT * FROM " + tableName; // 此时拼接是安全的
5. 数据库配置与权限
最小权限原则:应用使用的数据库账号应仅拥有
SELECT
、INSERT
、UPDATE
等必要权限,禁止DROP
、GRANT
等高危操作。禁用敏感函数:如 MySQL 的
LOAD_FILE
、INTO OUTFILE
。
6. 其他安全措施
隐藏错误信息:
try { // 执行数据库操作 } catch (SQLException e) { // 生产环境返回通用错误,避免泄露细节 logger.error("Database error", e); throw new RuntimeException("Internal server error"); }
使用安全工具:
OWASP ESAPI:提供安全的 SQL 转义方法。
SQL 注入扫描工具:集成
sqlmap
或SonarQube
进行代码审计。
总结:Java 防御 SQL 注入的核心规则
场景
安全做法
高风险做法(避免!)
执行 SQL 查询
使用 PreparedStatement
参数化
拼接字符串生成 SQL
动态表名/列名
白名单校验合法值
直接拼接用户输入
输入验证
正则表达式白名单过滤
仅在前端验证或不做验证
错误信息处理
记录日志,返回通用错误提示
返回详细数据库错误信息
ORM 框架
优先使用 Hibernate/JPA 的 Criteria 或 HQL
手动拼接 HQL 或 JPQL
关键点:
绝不信任用户输入:所有外部输入(包括 HTTP 请求参数、Cookie、Headers)均需验证和转义。
代码审查:定期检查项目中是否存在
Statement
或字符串拼接 SQL 的代码。依赖更新:确保数据库驱动和 ORM 框架保持最新版本,修复已知漏洞。
以上就是Java预防SQL注入的具体实践方法的详细内容,更多关于Java预防SQL注入的资料请关注脚本之家其它相关文章!
相关文章
解决IDEA的maven项目中没有新建Servlet文件的选项问题
这篇文章主要介绍了IDEA的maven项目中没有新建Servlet文件的选项问题及解决方法,本文给大家分享问题原因就解决方法,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2020-09-09Java中@ConditionalOnProperty注解使用
在Spring Boot中,@ConditionalOnProperty注解是一种方便的工具,用于根据应用程序配置文件中的属性值来控制Bean的创建和加载,本文就来介绍一下Java中@ConditionalOnProperty注解使用,感兴趣的可以了解一下2023-11-11Java NumberFormat格式化float类型的bug
今天小编就为大家分享一篇关于Java NumberFormat格式化float类型的bug,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧2018-10-10SpringCloud-Alibaba-Nacos启动失败解决方案
这篇文章主要介绍了SpringCloud-Alibaba-Nacos启动失败解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下2020-04-04spring-@Autowired注入与构造函数注入使用方式
这篇文章主要介绍了spring-@Autowired注入与构造函数注入使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教2023-12-12
最新评论