你好,我是风一样的树懒,一个工作十多年的后端开发,曾就职京东、阿里等多家互联网头部企业。
SQL注入攻击(SQL Injection)是指攻击者通过在应用程序输入的字段中插入恶意的 SQL 代码,从而影响数据库的查询逻辑,最终达到未授权访问、篡改或删除数据库的目的。为了有效防止 SQL 注入攻击,可以采取以下几种措施:
最有效的防止 SQL 注入攻击的方法是使用预编译语句(也叫参数化查询)。这确保了用户输入的数据不会被当作 SQL 代码执行,从而避免了 SQL 注入攻击。
String query = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement pstmt = connection.prepareStatement(query);
pstmt.setString(1, username); // 设置用户名参数
pstmt.setString(2, password); // 设置密码参数
ResultSet rs = pstmt.executeQuery();
通过这种方式,SQL 查询中的参数值(如 username 和 password)会作为参数传入,而不会被直接拼接成 SQL 语句,从而避免了 SQL 注入攻击。
存储过程是预定义的 SQL 语句集合,通过调用存储过程来执行数据库操作。存储过程通常会对输入数据进行严格的检查和处理,因此可以有效避免 SQL 注入。
CREATE PROCEDURE GetUserData (IN username VARCHAR(255), IN password VARCHAR(255))
BEGIN
SELECT * FROM users WHERE username = username AND password = password;
END;
调用存储过程时,输入参数不会直接拼接进 SQL 查询中,从而降低了 SQL 注入的风险。
输入验证:验证用户输入的数据是否符合预期类型和范围,例如检查是否为合法的数字、字母或预定格式(如邮箱、手机号等)。对于输入字段,限制其长度、类型和格式,减少恶意 SQL 注入的可能性。
过滤特殊字符:对于所有输入数据,尤其是字符串类型的输入,过滤掉可能被用来进行 SQL 注入的特殊字符,如 '、"、;、-- 等。
// 过滤掉可能的危险字符
String safeInput = userInput.replaceAll("[^a-zA-Z0-9]", "");
ORM 框架如 Hibernate、JPA、MyBatis 等,封装了数据库的访问层,通过对象的方式访问数据。这些框架通常会自动使用参数化查询,并对数据进行安全处理,避免了手动拼接 SQL 语句时可能带来的 SQL 注入风险。
String hql = "FROM User WHERE username = :username AND password = :password";
Query query = session.createQuery(hql);
query.setParameter("username", username);
query.setParameter("password", password);
List results = query.list();
最小权限原则:限制数据库用户的权限,只赋予其执行特定操作所需的权限。比如,应用程序的数据库用户不应拥有 DROP、DELETE 等修改结构的权限,避免攻击者通过 SQL 注入获取权限进行更严重的攻击。
避免暴露数据库错误信息,不向用户显示具体的错误信息(例如 SQL 语法错误或数据库连接失败)。攻击者可以利用这些错误信息来发现数据库的结构和漏洞。
开发时:开启详细的错误日志记录。
生产环境:只返回通用的错误消息,隐藏数据库的详细错误。
// 在捕获异常时,只返回通用错误信息
try {
// 执行数据库操作
} catch (SQLException e) {
// 记录日志,返回通用错误信息
log.error("Database error", e);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "An error occurred");
}
通常,面试可能大家能回答一到两条,特别是第六种情况,很容易忽略,且容易暴露数据库相关信息。
今天的内容就分享到这儿,喜欢的朋友可以关注,点赞。有什么不足的地方欢迎留言指出,您的关注是我前进的动力!