2026-04-22 10:25:33
Java防止SQL注入的核心方法是使用预编译语句(PreparedStatement)和参数化查询,其原理是通过分离SQL逻辑与用户输入,避免恶意代码被解析执行。以下是具体实践指南:

SQL注入是攻击者通过在输入中插入恶意SQL代码,欺骗系统执行非预期的数据库操作。例如:
SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1'='1'若代码直接拼接用户输入:
String query = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'";攻击者可通过输入admin' --或' OR '1'='1绕过验证,导致数据泄露或破坏。
二、为什么使用预编译语句(PreparedStatement)Java的PreparedStatement通过以下机制防止注入:

占位符?仅用于值的位置,不可用于表名、列名或SQL关键字。
使用setString()、setInt()等方法确保类型安全。
错误示例(易引发注入):
// 危险!拼接IN条件String ids = "1,2,3";String sql = "WHERE id IN (" + ids + ")"; // 攻击者可输入"1); DROP TABLE users--"正确做法:
MyBatis中应使用#{}而非${}:<!-- 安全:参数化查询 --><select id="getUser" resultType="User"> SELECT * FROM users WHERE id = #{id}</select><!-- 危险:字符串替换,可能注入 --><select id="getUser" resultType="User"> SELECT * FROM ${tableName} WHERE id = ${id}</select>
JPA Criteria API:提供类型安全的动态查询构建。
JPA的CriteriaBuilder:CriteriaBuilder cb = entityManager.getCriteriaBuilder();CriteriaQuery<User> query = cb.createQuery(User.class);Root<User> user = query.from(User.class);query.select(user).where(cb.equal(user.get("username"), username));
MyBatis的动态SQL标签(如<if>、<foreach>):<select id="searchUsers" resultType="User"> SELECT * FROM users <where> <if test="username != null">AND username = #{username}</if> <if test="status != null">AND status = #{status}</if> </where></select>

通过遵循上述实践,可有效防范SQL注入攻击,保障应用安全。