防SQL注入的最好实现方式是什么?
咨询区
-
LeonidasFett:
我的问题是:如何在 C# 中是使用SQL防注入
,我的模糊理解是可以通过限定应用程序接收的字段格式来实现最终目的,比如说:email字段只能接收email的格式,name字段不能输入特殊字符,以此类推,C#中应该也有对应的预定义方法。
这里想问大家有什么其他的思考。
回答区
-
Oliver
理论上你的做法是相对高效的,但是落地非常繁琐,其实你完全可以使用 SqlCommand
和 SqlParameters[]
实现SQL的参数化查询,它是一种非常通用的解决方案,无需特定字段使用特定格式的方式,参考如下代码:
private static void UpdateDemographics(Int32 customerID,
string demoXml, string connectionString)
{
// Update the demographics for a store, which is stored
// in an xml column.
string commandText = "UPDATE Sales.Store SET Demographics = @demographics "
+ "WHERE CustomerID = @ID;";
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand(commandText, connection);
command.Parameters.Add("@ID", SqlDbType.Int);
command.Parameters["@ID"].Value = customerID;
// Use AddWithValue to assign Demographics.
// SQL Server will implicitly convert strings into XML.
command.Parameters.AddWithValue("@demographics", demoXml);
try
{
connection.Open();
Int32 rowsAffected = command.ExecuteNonQuery();
Console.WriteLine("RowsAffected: {0}", rowsAffected);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
-
nerdybeardo
SQL 注入是一种很搞的问题,但还是有几种解决办法,要想减少风险,可以使用 ORM 框架 Linq2Entities, Linq2SQL, NHibrenate
等等,即使这么说,用这些框架还是有一定的注入风险的,SQL 注入的来源主要是用户界面的输入框,一个经典的例子是:假如你有一个登录界面,需要输入 用户名
和 密码
。
SELECT * FROM Users WHERE Username = '" + username + "' AND password = '" + password + "'"
此时有一个用户在input上输入 Admin'--
, 那么SQL语句将会发生质的变化。
SELECT * FROM Users WHERE Username = 'Admin' --' AND password = ''
要解决这种问题,就需要使用参数化查询 SQLParameter
来解决。
点评区
说实话, 对于SQL注入这块,我个人倾向于选择 ORM 和 裸SQL 之间的 Dapper 来进行处理,比如下面这样:
var list = Execute(conn =>
{
var sql = string.Format($@"select t.TagNo from xxx as c
join xxx as ct
on c.ID = ct.ID
where t.TagNo in @TagNo and c.Cus_ID = @CustomerID");
var query = conn.Query<string>(sql, new { TagNo = epcList, CustomerID = context.CustomerID }).ToList();
return query;
});
写法灵活,可控性高,效率也不错。