我有一个小问题,我有一个ASP.NET Webforms应用程序。我发送的url?id=X
X
是我的数据库索引或ID。
我有一个C#类文件来运行我的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;
我正在通过网址传递我的索引或ID,然后请求它并将其转换为字符串,然后使用ViewProduct(productId)
。
我不知道是什么语法或如何将id添加到我的C#字符串sql查询中。我试过了:
string cmdStr = "SELECT * Products WHERE Idx_ProductId = @0" + id;
string cmdStr = "SELECT * Products WHERE Idx_ProductId = {0}" + id;
我现在也无济于事。
答案 0 :(得分:4)
我很确定这会与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
类肯定没有使用它(您正在传递一个构建的命令字符串)。相反,你应该做这样的事情:
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 Server将其转换为:
DECLARE @id VARCHAR(100) = 'NULL; SELECT * FROM SensitiveData';
SELECT * FROM PRoducts WHERE Idx_ProductId = @id;
将不会返回任何结果(除非您的Idx_ProductId
实际上是该字符串),而不是返回第二个SELECT
的结果。
一些额外的阅读:
答案 1 :(得分:0)
Products.Idx_ProductId是什么类型的?
可能是字符串,而不是你需要使用引号:“... ='”+ id.Trim()+“'”;