Java预防SQL注入的具体实践方法

 更新时间:2025年01月22日 08:35:44   作者:Planter  
在 Java 中预防 SQL 注入的核心是 避免直接拼接 SQL 语句,并通过参数化查询、ORM 框架和严格的输入验证来实现安全防护,以下是具体实践方法,感兴趣的小伙伴跟着小编一起来看看吧

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. 数据库配置与权限

  • 最小权限原则:应用使用的数据库账号应仅拥有 SELECTINSERTUPDATE 等必要权限,禁止 DROPGRANT 等高危操作。

  • 禁用敏感函数:如 MySQL 的 LOAD_FILEINTO OUTFILE

6. 其他安全措施

隐藏错误信息:

try {
    // 执行数据库操作
} catch (SQLException e) {
    // 生产环境返回通用错误,避免泄露细节
    logger.error("Database error", e);
    throw new RuntimeException("Internal server error");
}

使用安全工具:

  • OWASP ESAPI:提供安全的 SQL 转义方法。

  • SQL 注入扫描工具:集成 sqlmapSonarQube 进行代码审计。

总结:Java 防御 SQL 注入的核心规则

场景

安全做法

高风险做法(避免!)

执行 SQL 查询

使用 PreparedStatement 参数化

拼接字符串生成 SQL

动态表名/列名

白名单校验合法值

直接拼接用户输入

输入验证

正则表达式白名单过滤

仅在前端验证或不做验证

错误信息处理

记录日志,返回通用错误提示

返回详细数据库错误信息

ORM 框架

优先使用 Hibernate/JPA 的 Criteria 或 HQL

手动拼接 HQL 或 JPQL

关键点

  • 绝不信任用户输入:所有外部输入(包括 HTTP 请求参数、Cookie、Headers)均需验证和转义。

  • 代码审查:定期检查项目中是否存在 Statement 或字符串拼接 SQL 的代码。

  • 依赖更新:确保数据库驱动和 ORM 框架保持最新版本,修复已知漏洞。

以上就是Java预防SQL注入的具体实践方法的详细内容,更多关于Java预防SQL注入的资料请关注脚本之家其它相关文章!

相关文章

  • 详解SpringBoot JPA常用注解的使用方法

    详解SpringBoot JPA常用注解的使用方法

    这篇文章主要介绍了SpringBoot JPA常用注解的使用方法,spring boot作为当前主流的技术,来看看常用的注解怎么用,如果有错误的地方还请指正,需要的朋友可以参考下
    2023-03-03
  • Java中String和StringBuffer及StringBuilder 有什么区别

    Java中String和StringBuffer及StringBuilder 有什么区别

    这篇文章主要介绍了Java中String和StringBuffer及StringBuilder 有什么区别,String 是 Java 语言非常基础和重要的类,更多相关内容需要的小伙伴可以参考下面文章内容
    2022-06-06
  • Scala中的mkString的具体使用方法

    Scala中的mkString的具体使用方法

    这篇文章主要介绍了Scala中的mkString的具体方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-06-06
  • 如何在Spring Boot中建立连接及测试

    如何在Spring Boot中建立连接及测试

    对于刚接触MQTT的开发者来说,了解如何在Spring Boot项目中集成MQTT客户端并建立连接是迈向实际应用的重要一步,今天,我将分享一个详细的入门指南,带你一步步在Spring Boot中建立MQTT连接,并通过JUnit进行简单的单元测试,感兴趣的朋友一起看看吧
    2024-12-12
  • SpringBoot实现文件的上传、下载和预览功能

    SpringBoot实现文件的上传、下载和预览功能

    在Spring Boot项目中实现文件的上传、下载和预览功能,可以通过使用Spring MVC的MultipartFile接口来处理文件上传,并使用HttpServletResponse或Resource来实现文件下载和预览,下面是如何实现这些功能的完整示例,需要的朋友可以参考下
    2024-08-08
  • Spring Boot接收单个String入参的解决方法

    Spring Boot接收单个String入参的解决方法

    这篇文章主要给大家介绍了关于Spring Boot接收单个String入参的解决方法,文中通过示例代码介绍的非常详细,对大家学习或者使用spring boot具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-11-11
  • java处理按钮点击事件的方法

    java处理按钮点击事件的方法

    下面小编就为大家带来一篇java处理按钮点击事件的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-04-04
  • spring启动后保证创建的对象不被垃圾回收器回收

    spring启动后保证创建的对象不被垃圾回收器回收

    最近看到一个问题是,spring在启动后如何保证创建的对象不被垃圾回收器回收?。所以本文结合jvm的垃圾回收机制和spring中的源代码做出自己的一点猜测。有需要的朋友们可以参考借鉴。
    2016-09-09
  • xxl-job如何滥用netty导致的问题及解决方案

    xxl-job如何滥用netty导致的问题及解决方案

    本篇文章讲解xxl-job作为一款分布式任务调度系统是如何滥用netty的,导致了怎样的后果以及如何修改源码解决这些问题,netty作为一种高性能的网络编程框架,十分受大家喜爱,今天就xxl-job滥用netty这一问题给大家详细下,感兴趣的朋友一起看看吧
    2021-05-05
  • 详解Spring/Spring boot异步任务编程WebAsyncTask

    详解Spring/Spring boot异步任务编程WebAsyncTask

    这篇文章主要介绍了详解Spring/Spring boot异步任务编程WebAsyncTask,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-06-06

最新评论