如果你看一下注释掉的内容,我可以通过直接在查询中添加用户输入来轻松实现这一点,但是当我尝试参数化时,没有任何值被添加到参数中......
此代码抛出错误
必须定义表变量@formTable
但问题是没有添加任何值,而不仅仅是表变量(通过用静态文本替换表名变量来验证)。
我在这个项目中有很多插入语句,结构与此完全相同。我在这做错了什么?
string constr = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
using (SqlConnection con = new SqlConnection(constr))
{
//string query = "UPDATE " + s.formTable + " SET " + s.column + " = '" + s.cellValue + "' WHERE MasterID = '" + s.id + "'";
string query = "UPDATE @formTable SET @column = @cellValue WHERE MasterID = @id;";
using (SqlCommand cmd = new SqlCommand(query))
{
//SqlParameter param = new SqlParameter("@formTable", s.formTable);
//cmd.Parameters.Add(param);
cmd.Parameters.AddWithValue("@formTable", s.formTable);
cmd.Parameters.AddWithValue("@column", s.column);
cmd.Parameters.AddWithValue("@cellValue", s.cellValue.ToString());
cmd.Parameters.AddWithValue("@id", s.id.ToString());
cmd.Connection = con;
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
}
答案 0 :(得分:1)
参数用于值,而不是对象标识符(表,列等),因此您唯一有效的参数是@cellValue
和@id
。
如果要根据用户输入动态设置表/列名称,您可能会查看字符串连接。 然而,这并不一定意味着SQL注入。您需要做的就是根据一组已知值验证用户输入,并使用串联中的已知值。
例如,假设您有一个包含所有表名的List<string>
。如果您的表永远不会改变,它可以是硬编码的,或者您可以通过数据库中的querying some system/schema tables使其更具动态性来填充它。
当用户输入表名的值时,请检查它是否在列表中。如果是,请使用列表中的匹配值。如果不是,则处理错误情况(例如向用户显示消息)。因此,即使您正在使用字符串连接,也不会在字符串中输入实际的用户输入。您只是连接已知的良好值,这与您现在的字符串文字没有什么不同。