C# ASP.NET,C如何将StringQuery传递给自定义SQL命令

C# ASP.NET,C如何将StringQuery传递给自定义SQL命令,c#,sql,asp.net,ado.net,C#,Sql,Asp.net,Ado.net,我有一个小问题,我有一个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(

我有一个小问题,我有一个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;
    }
}
如您所见,我的问题在于字符串cmdStr=SQL Query+variable

我通过URL传递我的索引或id,然后请求它并将其转换为字符串,然后使用ViewProductID

我不知道使用什么语法,也不知道如何将id添加到我的C字符串sql查询中。我试过:

string cmdStr = "SELECT * Products WHERE Idx_ProductId = @0" + id;
string cmdStr = "SELECT * Products WHERE Idx_ProductId = {0}" + id;

还有我目前没有的。

Products.Idx\u ProductId是什么类型的


可能是字符串,而不是需要使用引号:…='+id.Trim+'

我很确定这将是关于C中参数化查询的一些规范问题的重复,但显然没有一个

您应该参数化您的查询-如果您不这样做,您将面临恶意代码注入您的查询的风险。例如,如果您当前的代码可以在数据库上运行,那么让该代码执行以下操作就很简单:

// 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....
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?
    }
}
NET提供了非常简单的功能来参数化您的查询,而DBOps类在传入一个构建的命令字符串时肯定没有使用它。相反,您应该这样做:

// 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....
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;从SensiveData中选择*,它将被正确参数化。ADO.NET/Sql Server将此转换为:

DECLARE @id VARCHAR(100) = 'NULL; SELECT * FROM SensitiveData';
SELECT * FROM PRoducts WHERE Idx_ProductId = @id;
它将不返回任何结果,除非您有一个Idx_ProductId,它实际上就是该字符串,而不是返回第二次选择的结果

补充阅读:

VB.NET 特定于PHP,但有许多有用的地方
您迫切需要立即阅读、理解并开始参数化您的查询。这里有一个sql注入的教科书定义。通过querystring传递参数值是可以的,但您需要使用参数化查询,否则会受到攻击。您要查找的是ADO.NET,并且您将提供大量有关如何在c中创建数据库语句的示例。这是谷歌搜索结果的第一个例子:@Igor发布的链接很好,但它也建议使用AddWithValue。这样使用pass-through sql时会出现问题。它有时会错误地猜测数据类型。所有伟大的信息谢谢大家!我没有使用ADO.NET示例的原因是,我的SqlConnection和SqlCommands是在DBOps类文件中处理的,在其中为各种查询添加特殊参数是荒谬的,因此我将更改结构,但在此之前,我将检查参数化queries@Sean大人物或其他任何能帮忙的人,通过参数化您所指的我的查询,而不是选择*everything来选择要选择的参数ProductId、ProductName等?这将更适合作为注释。我认为这是解决方案的正确路径,但我们可能有一些错误的地方。是的,id是一个字符串。这仍然不是一个真正的好主意-查看此问题了解更多信息:谢谢,这帮了大忙!有点涵盖了所有内容,包括一个非常有助于再次感谢大家的例子。我花了几乎和我写这篇文章一样多的时间来寻找一个问题。很乐意帮忙。