.NET中的SQL注入预防

我通常在.NET中编写我的SQL

sql.Append("SELECT id, code, email FROM mytable WHERE variable = @variable "); 

然后做这样的事情:

 using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings[ConfigurationManager.AppSettings["defaultConnection"]].ConnectionString)) { using (SqlCommand myCommand = new SqlCommand(sql.ToString(), conn)) { myCommand.Parameters.AddWithValue("@variable", myVariableName"); ... 

但是当我得到的数据直接来自数据库时,我是否也应该这样做addParameter?

 likesql.Append(string.Format("SELECT group_id, like_text FROM likeTerms ORDER BY group_id ASC ")); DataTable dtLike = SqlHelper.GetDataTable(likesql.ToString()); foreach (DataRow dr in dtLike) { buildsql.Append(".... varId = " + dr["group_id"].ToString() + "..."); ... 

这可以接受吗? 什么是最佳做法?

你应该总是使用参数:

  • 数据库中的值来自哪里?
  • 在你的例子中,你能相信’group_id’没有被修改成你不期望的东西吗?

不相信

具有有限数据库访问权限的人可以直接注入其他地方使用的字段

性能

此外,它有助于提高性能。 缓存的执行计划将忽略参数的值,这意味着您每次参数更改时都会保存服务器不重新编译查询。

当您使用带参数的DbCommands时,参数永远不会“内联”到查询中。 而是将查询和参数数据传递给特殊的系统存储过程sp_executesql。 当它以这种方式完成时,无论您拥有什么参数数据都被视为完全相同,并且不会从查询字符串中解析出来; 因此,从未执行过可能已通过validation的注入命令。

使用参数是基于ADO.NET的数据访问层的最佳实践,无论数据来自何处,IMO是在此级别应该完成的唯一方式(如果您不使用ORM)。 您永远不应该将从Web或Windows窗体中检索的值连接到SQL语句中,如果您遵循该规则,为什么要以不同的方式实现它只是因为您确信或甚至不确定信息不是直接的来自用户? 遵循相同的模式,如果您公开该方法以持久保存用户指定的数据,则不会被刻录。

这是可以接受的(在某种意义上,如果您知道限制,您有时可能正常工作)。

使用数据库中的值并使用字符串连接构建SQL查询是不错的做法 – 否。

即你的样本如果“group_id”是"'--"怎么办?

我建议使用存储过程,但这是可以接受的我还建议您在将参数分配给查询之前清理它们