2021-05-20 19:09:12
参数化查询是一种通过使用参数占位符构建SQL语句的方法,而非直接拼接用户输入,能有效防止SQL注入攻击,确保用户输入被数据库当作纯数据处理而非代码执行。
直接拼接用户输入的风险:若应用程序直接将用户输入拼接到SQL语句中,攻击者可输入恶意字符串(如' OR '1'='1)篡改SQL逻辑。例如:
SELECT * FROM Users WHERE Username = '' OR '1'='1' --'此语句会绕过身份验证,返回所有用户数据,造成严重安全漏洞。
参数化查询的防护机制:参数化查询强制将用户输入作为数据传递,即使输入包含单引号或SQL关键字(如DROP TABLE),也会被数据库视为普通文本,无法影响SQL结构。
在C#中,通过SqlCommand配合SqlParameter实现参数化查询,避免字符串拼接。以下是具体步骤和示例:
1. 基本实现(使用AddWithValue)using (SqlConnection conn = new SqlConnection(connectionString)){ conn.Open(); string sql = "SELECT * FROM Users WHERE Username = @username AND Password = @password"; using (SqlCommand cmd = new SqlCommand(sql, conn)) { cmd.Parameters.AddWithValue("@username", userInputUsername); cmd.Parameters.AddWithValue("@password", userInputPassword); using (SqlDataReader reader = cmd.ExecuteReader()) { while (reader.Read()) { // 处理查询结果 } } }}@username和@password是参数占位符,而非字符串拼接。
AddWithValue方法自动处理参数类型和转义,即使输入包含特殊字符(如单引号)也不会被解析为SQL代码。
虽然AddWithValue简便,但建议显式定义参数类型和长度,避免类型推断错误或数据库执行计划问题:
cmd.Parameters.Add("@username", SqlDbType.VarChar, 50).Value = userInputUsername;cmd.Parameters.Add("@password", SqlDbType.VarChar, 100).Value = userInputPassword;防止因数据类型不匹配导致的潜在错误(如字符串被误判为整数)。
优化数据库执行计划重用,提升性能。
杜绝SQL注入:即使攻击者输入恶意字符串(如admin'; DROP TABLE Users;--),参数化查询也会将其视为普通文本,不会执行额外的SQL命令。
兼容复杂场景:适用于INSERT、UPDATE、DELETE等所有SQL操作,例如:
string sql = "INSERT INTO Users (Username, Password) VALUES (@username, @password)";cmd.Parameters.AddWithValue("@username", "newUser");cmd.Parameters.AddWithValue("@password", "securePass123");坚持参数化查询是防御SQL注入的最有效手段之一,也是开发安全应用程序的基本要求。