ASP.NET,C# 如何将 StringQuery 传递给自定义 SQL 命令
ASP.NET, C# How to Pass a StringQuery to a custom SQL Command
我有一个小问题,我有一个 ASP.NET Webforms 应用程序。我发送 url?id=X
是 X
是我的数据库索引或 ID。
我有一个 C# class 文件用于 运行 我的 SQL 连接和查询。这是代码:
public DataTable ViewProduct(string id)
{
try
{
string cmdStr = "SELECT * Products WHERE Idx_ProductId = " + id;
DBOps dbops = new DBOps();
DataTable vpTbl = dbops.RetrieveTable(cmdStr, ConfigurationManager.ConnectionStrings["MyDatabase"].ConnectionString);
return vpTbl;
}
catch (Exception e)
{
return null;
}
}
所以你可以看到我的问题在于 string cmdStr = "SQL Query" + variable;
我通过 URL 传递我的索引或 ID,然后请求它并将其转换为字符串,然后使用 ViewProduct(productId)
.
我不知道用什么语法或如何将 id 添加到我的 C# 字符串 sql 查询中。我试过:
string cmdStr = "SELECT * Products WHERE Idx_ProductId = @0" + id;
string cmdStr = "SELECT * Products WHERE Idx_ProductId = {0}" + id;
还有我目前有的也无济于事。
Products.Idx_ProductId 是什么类型?
可能是字符串,您需要使用引号:"... = '" + id.Trim() + "'";
我非常确定这将是关于 C# 中参数化查询的一些规范问题的重复,但显然没有(请参阅 this)!
您应该参数化您的查询 - 如果不这样做,您 运行 有可能将一段恶意代码自身注入到您的查询中。例如,如果您当前的代码可以 运行 针对数据库,那么让该代码执行如下操作将是微不足道的:
// string id = "1 OR 1=1"
"SELECT * Products WHERE Idx_ProductId = 1 OR 1=1" // will return all product rows
// string id = "NULL; SELECT * FROM UserPasswords" - return contents of another table
// string id = "NULL; DROP TABLE Products" - uh oh
// etc....
ADO.NET 提供了非常简单的功能来参数化您的查询,而您的 DBOps
class 肯定不会使用它(您正在传递一个构建的命令字符串)。相反,你应该这样做:
public DataTable ViewProduct(string id)
{
try
{
string connStr = ConfigurationManager.ConnectionStrings["MyDatabase"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connStr))
{
conn.Open();
using (SqlCommand cmd = conn.CreateCommand())
{
// @id is very important here!
// this should really be refactored - SELECT * is a bad idea
// someone might add or remove a column you expect, or change the order of columns at some point
cmd.CommandText = "SELECT * Products WHERE Idx_ProductId = @id";
// this will properly escape/prevent malicious versions of id
// use the correct type - if it's int, SqlDbType.Int, etc.
cmd.Parameters.Add("@id", SqlDbType.Varchar).Value = id;
using (SqlDataReader reader = cmd.ExecuteReader())
{
DataTable vpTbl = new DataTable();
vpTbl.Load(reader);
return vpTbl;
}
}
}
}
catch (Exception e)
{
// do some meaningful logging, possibly "throw;" exception - don't just return null!
// callers won't know why null got returned - because there are no rows? because the connection couldn't be made to the database? because of something else?
}
}
现在,如果有人试图通过 "NULL; SELECT * FROM SensitiveData",它将被正确地参数化。 ADO.NET/Sql 服务器会将其转换为:
DECLARE @id VARCHAR(100) = 'NULL; SELECT * FROM SensitiveData';
SELECT * FROM PRoducts WHERE Idx_ProductId = @id;
这将 return 没有结果(除非你有一个 Idx_ProductId
实际上是那个字符串)而不是 return 第二个 SELECT
的结果。
补充阅读:
- https://security.stackexchange.com/questions/25684/how-can-i-explain-sql-injection-without-technical-jargon
- Difference between Parameters.Add and Parameters.AddWithValue
- SQL injection on INSERT
- Avoiding SQL injection without parameters
- How do I create a parameterized SQL query? Why Should I? (VB.NET)
- How can I prevent SQL injection in PHP?(PHP 具体,但有很多有用的要点)
- Is there a canonical question telling people why they should use SQL parameters?
我有一个小问题,我有一个 ASP.NET Webforms 应用程序。我发送 url?id=X
是 X
是我的数据库索引或 ID。
我有一个 C# class 文件用于 运行 我的 SQL 连接和查询。这是代码:
public DataTable ViewProduct(string id)
{
try
{
string cmdStr = "SELECT * Products WHERE Idx_ProductId = " + id;
DBOps dbops = new DBOps();
DataTable vpTbl = dbops.RetrieveTable(cmdStr, ConfigurationManager.ConnectionStrings["MyDatabase"].ConnectionString);
return vpTbl;
}
catch (Exception e)
{
return null;
}
}
所以你可以看到我的问题在于 string cmdStr = "SQL Query" + variable;
我通过 URL 传递我的索引或 ID,然后请求它并将其转换为字符串,然后使用 ViewProduct(productId)
.
我不知道用什么语法或如何将 id 添加到我的 C# 字符串 sql 查询中。我试过:
string cmdStr = "SELECT * Products WHERE Idx_ProductId = @0" + id;
string cmdStr = "SELECT * Products WHERE Idx_ProductId = {0}" + id;
还有我目前有的也无济于事。
Products.Idx_ProductId 是什么类型?
可能是字符串,您需要使用引号:"... = '" + id.Trim() + "'";
我非常确定这将是关于 C# 中参数化查询的一些规范问题的重复,但显然没有(请参阅 this)!
您应该参数化您的查询 - 如果不这样做,您 运行 有可能将一段恶意代码自身注入到您的查询中。例如,如果您当前的代码可以 运行 针对数据库,那么让该代码执行如下操作将是微不足道的:
// string id = "1 OR 1=1"
"SELECT * Products WHERE Idx_ProductId = 1 OR 1=1" // will return all product rows
// string id = "NULL; SELECT * FROM UserPasswords" - return contents of another table
// string id = "NULL; DROP TABLE Products" - uh oh
// etc....
ADO.NET 提供了非常简单的功能来参数化您的查询,而您的 DBOps
class 肯定不会使用它(您正在传递一个构建的命令字符串)。相反,你应该这样做:
public DataTable ViewProduct(string id)
{
try
{
string connStr = ConfigurationManager.ConnectionStrings["MyDatabase"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connStr))
{
conn.Open();
using (SqlCommand cmd = conn.CreateCommand())
{
// @id is very important here!
// this should really be refactored - SELECT * is a bad idea
// someone might add or remove a column you expect, or change the order of columns at some point
cmd.CommandText = "SELECT * Products WHERE Idx_ProductId = @id";
// this will properly escape/prevent malicious versions of id
// use the correct type - if it's int, SqlDbType.Int, etc.
cmd.Parameters.Add("@id", SqlDbType.Varchar).Value = id;
using (SqlDataReader reader = cmd.ExecuteReader())
{
DataTable vpTbl = new DataTable();
vpTbl.Load(reader);
return vpTbl;
}
}
}
}
catch (Exception e)
{
// do some meaningful logging, possibly "throw;" exception - don't just return null!
// callers won't know why null got returned - because there are no rows? because the connection couldn't be made to the database? because of something else?
}
}
现在,如果有人试图通过 "NULL; SELECT * FROM SensitiveData",它将被正确地参数化。 ADO.NET/Sql 服务器会将其转换为:
DECLARE @id VARCHAR(100) = 'NULL; SELECT * FROM SensitiveData';
SELECT * FROM PRoducts WHERE Idx_ProductId = @id;
这将 return 没有结果(除非你有一个 Idx_ProductId
实际上是那个字符串)而不是 return 第二个 SELECT
的结果。
补充阅读:
- https://security.stackexchange.com/questions/25684/how-can-i-explain-sql-injection-without-technical-jargon
- Difference between Parameters.Add and Parameters.AddWithValue
- SQL injection on INSERT
- Avoiding SQL injection without parameters
- How do I create a parameterized SQL query? Why Should I? (VB.NET)
- How can I prevent SQL injection in PHP?(PHP 具体,但有很多有用的要点)
- Is there a canonical question telling people why they should use SQL parameters?