面试题答案
一键面试SQL注入风险原因
在使用JDBC连接MySQL数据库时,如果直接将用户输入的数据拼接到SQL语句中,就会产生SQL注入风险。因为用户输入的数据可能包含恶意的SQL语句片段,这些片段会改变原本SQL语句的逻辑和执行意图,导致数据库的信息泄露、数据被篡改或删除等安全问题。例如,原本的SQL查询语句是 SELECT * FROM users WHERE username = '${userInput}' AND password = '${passwordInput}'
,如果 userInput
被恶意输入为 ' OR '1' = '1
,整个SQL语句就会变为 SELECT * FROM users WHERE username = '' OR '1' = '1' AND password = '${passwordInput}'
,这样无论密码是否正确,都会返回所有用户数据。
处理SQL注入问题的方法及代码示例
1. 使用PreparedStatement
PreparedStatement
是预编译的SQL语句对象,它将SQL语句和参数分开处理,避免了直接拼接用户输入数据带来的风险。
示例代码:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class JdbcExample {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/mydb";
String user = "root";
String password = "password";
String username = "testUser";
String passwordInput = "testPassword";
try (Connection connection = DriverManager.getConnection(url, user, password)) {
String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
try (PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
preparedStatement.setString(1, username);
preparedStatement.setString(2, passwordInput);
try (ResultSet resultSet = preparedStatement.executeQuery()) {
if (resultSet.next()) {
System.out.println("User found!");
} else {
System.out.println("User not found.");
}
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
2. 使用ORM框架(以Hibernate为例)
ORM(对象关系映射)框架将Java对象与数据库表进行映射,通过框架的操作方法来执行数据库操作,而不是直接编写SQL语句,大大降低了SQL注入的风险。
首先,需要添加Hibernate相关依赖(以Maven为例):
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.6.10.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.31</version>
</dependency>
示例代码:
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateExample {
public static void main(String[] args) {
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
String username = "testUser";
String password = "testPassword";
// 假设User是映射到users表的实体类
User user = session.createQuery("FROM User WHERE username = :username AND password = :password", User.class)
.setParameter("username", username)
.setParameter("password", password)
.uniqueResult();
if (user != null) {
System.out.println("User found!");
} else {
System.out.println("User not found.");
}
session.close();
sessionFactory.close();
}
}
这里 User
是一个根据数据库 users
表映射生成的Java实体类,Hibernate通过 createQuery
方法并使用命名参数的方式来避免SQL注入。