【发布时间】:2012-04-26 20:37:36
【问题描述】:
我在尝试参数化 ASP 应用程序使用的现有 C# 类中的某些“动态”SQL 构建时遇到问题。环境是:
- Win Server 2008
- .NET 3.0
- C#
- DB2 9.x([IBM][CLI 驱动程序][DB2])
现有代码只是将 SQL 与长 SQL 字符串中的参数字符串连接起来——这当然存在 SQL 注入的风险。每当我看到这一点时,我的做法就是,我倾向于更改代码以使用参数。但是有了这段代码,我失败了。我试过“@”,也试过“?” - 后者是我理解的 ODBC 所必需的。
这是我编译并运行的简化代码 sn-p(请原谅我的格式不正确 - 这是我的第一个问题):
private DataSet test(String schemaName )
{
String sortField = "TABLE_NAME.COLUMN_NAME";
String sortDirection = "ASC";
OdbcConnection conn = new OdbcConnection();
DataSet ds = new DataSet();
string connStr = ConfigurationManager.AppSettings[schemaName] + dbUser;
try
{
conn.ConnectionString = connStr;
OdbcCommand cmd = new OdbcCommand("SELECT * FROM TABLE_NAME ORDER BY ? ? ");
cmd.Connection = conn;
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add(sortField);
cmd.Parameters.Add(sortDirection);
logger.log("cmd SQL = \t" + cmd.CommandText );
OdbcDataAdapter da = new OdbcDataAdapter(cmd);
da.Fill(ds);
return ds;
}
catch (Exception ex)
{
ex.Data.Add("Location:", "test()");
ex.Data.Add("Connection", conn.ConnectionString);
logger.logException(ex);
throw ex;
}
finally
{
conn.Close();
}
}
日志打印输出:
cmd SQL = SELECT * FROM TABLE_NAME ORDER BY ? ?
TABLE_NAME 当然是我要查询的表。
我得到的回报是这个(删除了一些专有信息:
异常发生在 2012 年 4 月 26 日下午 12:29:41 错误 [42601] [IBM][CLI Driver][DB2] SQL0104N 意外的标记“?”在“”之后发现。 预期的令牌可能包括:“MICROSECONDS MICROSECOND SECONDS SECOND MINUTES MINUTE HOURS”。SQLSTATE=42601 在 System.Data.Odbc.OdbcConnection.HandleError(OdbcHandle hrHandle,RetCode retcode)连接驱动程序 = {IBM DB2 ODBC 驱动程序}; .....
不允许将其更改为存储过程。
不允许升级到更高版本的 .NET。
不允许更改/升级 ODBC 驱动程序。
我所看到的向我表明“?”参数没有被替换。
我已经尝试过 AddWithValue() 并且我已经尝试过 Add(OdbcType.VarChar).Value = sortField(或类似的东西)。
我有点不知所措了——所有的谷歌搜索和搜索都向我表明上面的代码应该可以工作,但到目前为止,我还无法获得用变量替换的 SQL 中的参数。
提前致谢。
【问题讨论】:
-
哦,我也试过“new OdbcParameter(...)”。
-
我不相信你正在尝试的是真正的参数。 “字段名 = ?”是一个参数。在这种情况下,您可以将查询构建为:" ... ORDER BY " + sortField + " " + sortDirection
-
不是 SQL 参数,而是将 C# 参数替换为 SQL 以防止 SQL 注入。我的示例进行了简化,但真正的查询包含用户可以输入的字符串。我想保护 SQL 免受将孩子命名为“Bobby Tables”(“Robert');DROP TABLE Students;--”)的父母。
-
但是排序顺序和方向来自代码,而不是用户输入。所以 concat 是安全的。