Java 如何通过代码加固防止数据库 SQL 注入漏洞?
一、SQL 注入漏洞简介
SQL 注入是一种常见的 Web 安全漏洞,攻击者通过在应用程序的输入字段中插入恶意的 SQL 语句,从而非法获取、修改或删除数据库中的数据。例如,在登录表单的用户名或密码输入框中,攻击者输入特定的 SQL 代码,可能绕过身份验证机制,直接进入系统,造成严重的数据泄露和系统安全问题。
二、传统 SQL 语句拼接引发的问题
在早期的 Java 数据库操作中,使用 JDBC 时如果采用简单的字符串拼接来构建 SQL 语句,就容易产生 SQL 注入漏洞。例如:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class SQLInjectionExample {
public static void main(String[] args) {
String username = "admin' OR '1'='1";
String password = "any";
String url = "jdbc:mysql://localhost:3306/mydb";
String user = "root";
String pass = "root";
try {
Connection connection = DriverManager.getConnection(url, user, pass);
Statement statement = connection.createStatement();
String sql = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'";
ResultSet resultSet = statement.executeQuery(sql);
if (resultSet.next()) {
System.out.println("Login successful!");
} else {
System.out.println("Login failed!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
上述代码中,恶意的 username
值会改变 SQL 语句的逻辑,导致攻击者可以绕过密码验证。
三、防止 SQL 注入的方法
(一)使用 PreparedStatement
PreparedStatement
是 JDBC 提供的一种预编译的 SQL 语句对象,它会将 SQL 语句和参数分开处理,从而有效防止 SQL 注入。示例如下:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class PreparedStatementExample {
public static void main(String[] args) {
String username = "admin' OR '1'='1";
String password = "any";
String url = "jdbc:mysql://localhost:3306/mydb";
String user = "root";
String pass = "root";
try {
Connection connection = DriverManager.getConnection(url, user, pass);
String sql = "SELECT * FROM users WHERE username =? AND password =?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, username);
preparedStatement.setString(2, password);
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
System.out.println("Login successful!");
} else {
System.out.println("Login failed!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
在 PreparedStatement
中,?
是占位符,参数会被安全地传递,不会影响 SQL 语句的结构。
(二)使用 ORM 框架
如 Hibernate、MyBatis 等。以 MyBatis 为例,它提供了强大的映射功能,并且在处理 SQL 时,也会采取类似预编译的方式防止 SQL 注入。
在 MyBatis 的 XML 映射文件中,可以这样定义 SQL:
<select id="findUserByUsernameAndPassword" parameterType="map" resultType="User">
SELECT * FROM users WHERE username = #{username} AND password = #{password}
</select>
这里的 #{}
会自动对参数进行安全处理,防止恶意 SQL 代码注入。
(三)输入验证与过滤
除了上述数据库操作层面的防范,对用户输入进行严格的验证和过滤也是重要的手段。可以使用正则表达式等方式,限制输入的字符类型和长度,只允许符合要求的字符进入系统,从而从源头上减少 SQL 注入的风险。
通过综合运用上述方法,Java 开发者可以有效地加固代码,防止数据库 SQL 注入漏洞,保障系统的数据安全和稳定性。
本文链接:https://blog.runxinyun.com/post/751.html 转载需授权!
留言0