WinForms中DataGridView参数替换及SQL注入防范方案
解决BindingSource.Filter的SQL注入风险问题
原代码的核心问题是BindingSource.Filter不支持SQL参数化,它遵循DataView的筛选语法,和SqlCommand的参数机制完全不兼容,直接用SqlCommand参数不仅无效,还会导致筛选功能失效。要防范注入,得手动安全处理用户输入的特殊字符后再拼接筛选条件。
关键防范要点
- DataView筛选语法中,字符串用单引号
'包裹,用户输入的单引号必须转义为两个单引号'',否则会破坏筛选语句结构,引发注入风险。 - 如果使用
LIKE通配符(%、_),若不想让用户通过通配符扩大筛选范围,需要把这些字符转义为[%]、[_];若允许用户使用通配符,则直接保留。
修改后的代码
private void button1_Click(object sender, EventArgs e) { BindingSource bs = new BindingSource(); StringBuilder sb = new StringBuilder(); bs.DataSource = dataGridView1.DataSource; // 处理DealClassification筛选条件 if (!string.IsNullOrWhiteSpace(textBox1.Text)) { string safeDealText = EscapeFilterValue(textBox1.Text); sb.Append($"DealClassification LIKE '%{safeDealText}%'"); } // 处理TraderName筛选条件 if (!string.IsNullOrWhiteSpace(textBox2.Text)) { string safeTraderText = EscapeFilterValue(textBox2.Text); if (sb.Length > 0) { sb.Append(" AND "); } sb.Append($"TraderName LIKE '%{safeTraderText}%'"); } // 应用筛选,无条件时清空Filter恢复全量数据 bs.Filter = sb.Length > 0 ? sb.ToString() : string.Empty; dataGridView1.DataSource = bs; } // 统一处理筛选值的特殊字符转义 private string EscapeFilterValue(string input) { if (string.IsNullOrEmpty(input)) return input; // 必须:转义单引号,避免破坏筛选语句结构 string escaped = input.Replace("'", "''"); // 可选:转义LIKE通配符,限制用户通过通配符扩大筛选范围 escaped = escaped.Replace("%", "[%]").Replace("_", "[_]"); return escaped; }
代码说明
- 移除无用的SqlCommand:SqlCommand的参数机制对BindingSource.Filter完全不适用,直接用StringBuilder拼接筛选逻辑。
- 统一转义特殊字符:通过
EscapeFilterValue方法处理用户输入,确保单引号被转义,避免注入风险;可选转义通配符,控制筛选范围。 - 严谨的空值判断:用
string.IsNullOrWhiteSpace替代简单的空字符串判断,覆盖空白字符场景。 - 无筛选场景处理:当没有有效筛选条件时,清空Filter,恢复显示所有数据。
这样处理后,即使用户输入带有单引号或恶意内容(比如' OR 1=1),也会被转义为安全的字符串,既不会引发注入风险,也能保证筛选功能正常运行。
内容的提问来源于stack exchange,提问作者Tomislav Muic
相关产品推荐
相关产品推荐

