JAVA 在做 SQL 注入防御时有哪些方法
1. 使用预处理语句
这是 Java 中防御 SQL 注入最主要、最安全的方法。它与数据库通信时,会先发送 SQL 语句的模板,数据库编译好后,再将用户数据作为参数发送。这样,数据库只将数据视为数据,不会当作可执行的 SQL 命令
JDBC 示例
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class UserDAO {
public void getUserData(String username) {
String sql = "SELECT * FROM users WHERE username = ?";
try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testdb", "user", "password");
PreparedStatement pstmt = conn.prepareStatement(sql)) {
// 1. 设置参数,将用户输入绑定到占位符
pstmt.setString(1, username);
// 2. 执行查询
try (ResultSet rs = pstmt.executeQuery()) {
if (rs.next()) {
System.out.println("User found: " + rs.getString("username"));
} else {
System.out.println("User not found.");
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
- 核心: 使用
?
作为占位符,然后通过pstmt.setString()
、pstmt.setInt()
等方法将用户输入绑定到这些占位符上
2. 使用 ORM 框架
如果你使用 Java 生态系统中的主流框架,如 Spring Boot、Hibernate、MyBatis,那么 ORM 是首选。这些框架将面向对象编程与关系型数据库操作结合起来,从根本上消除了手动编写 SQL 的需要,从而自动防御 SQL 注入
Hibernate 示例
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import com.example.model.User;
public class UserRepository {
private final SessionFactory sessionFactory;
public User findByUsername(String username) {
try (Session session = sessionFactory.openSession()) {
// HQL (Hibernate Query Language) 示例
// Hibernate 会自动处理参数绑定
Query<User> query = session.createQuery("from User where username = :username", User.class);
query.setParameter("username", username);
return query.uniqueResult();
}
}
}
- 核心: Hibernate 等 ORM 框架在底层使用预处理语句来执行所有数据库操作,因此你不需要担心 SQL 注入问题
3. 最小权限原则
这是一个重要的安全实践
- 不要使用数据库的管理员账户(如
root
)来运行应用程序 - 为你的应用程序创建专用的数据库用户,并只授予其完成任务所需的最小权限。例如,一个只进行读取操作的服务,其数据库用户就应该只有
SELECT
权限
防御方法 | 优点 | 缺点 | 推荐度 |
---|---|---|---|
预处理语句 | 最安全、最彻底的防御;将数据与SQL代码分离。 | 需要手动编写SQL,语法略显繁琐。 | 最高 |
ORM框架 | 从根本上杜绝SQL注入;开发效率高;代码可读性好。 | 需要学习框架;不适用于简单或无框架项目。 | 非常高 |
最小权限 | 降低攻击后的危害。 | 无法从根本上防御注入。 | 非常高(作为安全原则) |