You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何保护C#中动态生成的SQL查询免受SQL注入?附示例代码

防护该SQL查询免受SQL注入的最佳方案

首先得说,你现在这段直接拼接字符串的代码,简直是SQL注入的“完美靶子”——不管字典里的内容是什么,只要values.Value里混了恶意内容(比如' OR 1=1--),整个UPDATE语句就会被彻底篡改,搞不好能把整张表的数据改乱,甚至触发删表这类高危操作。

在对字典内容一无所知的情况下,使用参数化查询是唯一靠谱的黄金方案,它能从根源上把用户输入(也就是字典里的键值)和SQL语句本身彻底分开,数据库驱动会自动处理参数的转义逻辑,把参数当作纯数据而非SQL指令的一部分。

具体怎么改你的代码?

以C# + Oracle数据库为例,修改后的代码大概是这样:

void UpdateData(Dictionary<string, string> data)
{
    if (data == null || data.Count == 0)
        return;

    // 构建参数化的SET子句片段,同时准备参数集合
    var setClauses = new List<string>();
    var parameters = new List<OracleParameter>();

    foreach (var kvp in data)
    {
        // Oracle用冒号作为参数前缀,将列名对应到参数名
        var paramName = $":{kvp.Key}";
        setClauses.Add($"{kvp.Key} = {paramName}");
        // 把字典的值添加为参数
        parameters.Add(new OracleParameter(paramName, kvp.Value));
    }

    // 加上固定的modDate更新逻辑
    setClauses.Add("modDate = sysdate");

    // 拼接出完整的参数化SQL
    string query = $"UPDATE tablename SET {string.Join(", ", setClauses)}";

    // 执行SQL(这里假设你已经有合法的数据库连接字符串)
    using (var conn = new OracleConnection("your_connection_string"))
    {
        conn.Open();
        using (var cmd = new OracleCommand(query, conn))
        {
            cmd.Parameters.AddRange(parameters.ToArray());
            cmd.ExecuteNonQuery();
        }
    }
}

额外要注意的点

  • 虽然参数化能完美处理值的注入风险,但字典的**键(也就是列名)**如果是不可信来源的话,还是有风险——比如有人把键改成username; DROP TABLE users--,直接拼进去就会出大问题。所以最好提前维护一个允许更新的列名白名单,遍历字典时先检查键是否在白名单里,只有合法的列才允许加入SET子句。
  • 绝对不要依赖手动转义字符串(比如把单引号改成双单引号),这种方法不仅容易出错,不同数据库的转义规则还不一样,根本防不住所有注入场景。
  • 始终使用数据库提供的参数化API,不要自己造轮子,这是经过无数验证的安全实践。

内容的提问来源于stack exchange,提问作者Neema

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:31:24