什么是将参数传递给 SQL,我为什么需要它?

Posted

技术标签:

【中文标题】什么是将参数传递给 SQL,我为什么需要它?【英文标题】:What is passing parameters to SQL and why do I need it? 【发布时间】:2011-03-14 01:46:36 【问题描述】:

这里是初学者:

在这个answer 关于如何将数据插入SQL Server 的问题中,他提到了传递参数而不是像我目前使用的字符串连接。

这对于安全来说真的有必要吗?如果是这样,传递参数究竟是什么?当我用谷歌搜索时,我得到了很多关于存储过程的信息。那是我想要的吗,我不知道存储过程....但是。

如果您能指出正确的方向,我将不胜感激。

谢谢。

编辑:

好的,这就是我得到的。似乎可以正确更新数据库,最终我会将硬编码的整数更改为标签的输入。请确认我如何做到这一点是否不易受到任何 sql 注入或黑客攻击。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Security;

using System.Data;
using System.Data.Sql;
using System.Data.SqlClient;



public partial class Stats : System.Web.UI.Page


    public SqlDataReader DataReader;
    public SqlCommand Command;
    string queryString = ("INSERT INTO UserData (UserProfileID, ConfidenceLevel, LoveLevel, HappinessLevel) VALUES (@UID, @CL, @LL, @HL);");
    //string queryString = ("INSERT INTO UserData (UserProfileID, ConfidenceLevel, LoveLevel, HappinessLevel) VALUES ('a051fc1b-4f51-485b-a07d-0f378528974e', 2, 2, 2);"); 

    protected void Page_Load(object sender, EventArgs e)
    
       LabelUserID.Text = Membership.GetUser().ProviderUserKey.ToString();

    

    protected void Button1_Click(object sender, EventArgs e)
    

        //connect to database
        mysqlConnection database = new MySqlConnection();
        database.CreateConn(); 

        //create command object
        Command = new SqlCommand(queryString, database.Connection);

        //add parameters. used to prevent sql injection
        Command.Parameters.Add("@UID", SqlDbType.UniqueIdentifier);
        Command.Parameters["@UID"].Value = Membership.GetUser().ProviderUserKey;

        Command.Parameters.Add("@CL", SqlDbType.Int);
        Command.Parameters["@CL"].Value = 9;

        Command.Parameters.Add("@LL", SqlDbType.Int);
        Command.Parameters["@LL"].Value = 9;

        Command.Parameters.Add("@HL", SqlDbType.Int);
        Command.Parameters["@HL"].Value = 9;

        Command.ExecuteNonQuery(); 


    


【问题讨论】:

我最自豪的时刻:***.com/questions/332365/… @Will - 我喜欢小鲍比桌。排名靠前的是他们关于 Gotos 的脱衣舞。 除了学习编写参数化查询之外,我还建议阅读 Justin Clarke 的一本书,名为“SQL 注入攻击与防御”,他在其中深入讨论了 SQL 注入是如何发生的,如何防范它包括 .NET 在内的各种语言,如何测试它等等。不错的读物。 @Thomas:听起来不错。我将不得不以某种方式抽出时间....我是我这个项目的一个人! 【参考方案1】:

将参数传递给 SQL 使您不必构建动态 SQL 字符串。

构建动态 SQL 语句存在巨大的安全风险,因为人们可以将自己的 SQL 代码注入您的应用程序,可能会对您的数据执行不需要的命令。

有一些很好的可能的 SQL 注入攻击示例:

SQL Injection Attacks by Example

将参数传递给 SQL 语句有两种方法。一种是使用您提到的存储过程。另一种是使用参数化查询(这实际上是我更喜欢的)。

.NET 中的参数化查询实际上非常简单:

using(SqlConnection conn = new SqlConnection(connString))

    SqlCommand command = 
        new SqlCommand("SELECT * FROM Users WHERE Username = @Username", conn);

    command.Parameters.Add(new SqlParameter("@Username", "Justin Niessner"));

    SqlDataAdapter adapter = new SqlDataAdapter(command);
    DataTable dt = new DataTable();

    adapter.Fill(dt);

在该示例中,参数为@Username,我们使用SqlCommand 对象的Parameters 集合来传递值。

【讨论】:

对刚开始的人的参数化查询有什么好的参考吗? @Greg 它看起来很简单。【参考方案2】:

它会保护你免受小鲍比桌的伤害。

http://xkcd.com/327/

【讨论】:

哈哈,哇哦,那一定是我看过的最极客的漫画了……但我相信它会变得更糟!无论如何,谢谢,我明白你在说什么。【参考方案3】:

这是一个例子:

        SqlConnection myConn = new SqlConnection("my connection string");

        SqlCommand myCmd = new SqlCommand("myStoredProcName", myConn);

        myCmd.CommandType = CommandType.StoredProcedure;

        myCmd.Parameters.AddWithValue("@cGroupID", 0).Direction = ParameterDirection.InputOutput;
        myCmd.Parameters.AddWithValue("@gType", "C");
        myCmd.Parameters.AddWithValue("@requirement", "Y");
        myCmd.Parameters.AddWithValue("@usercode", "XX");

        myConn.Open();
        myCmd.ExecuteNonQuery();

        int covID = (int)myCmd.Parameters["@cGroupID"].Value;

使用参数是防止某些错误并帮助停止注入向量的好方法。它还允许 OUTPUT 参数,如上面的示例中 cGroupID 返回一个我可以访问的值。

【讨论】:

【参考方案4】:

简单连接字符串的主要问题是它经常使您容易受到 SQL 注入攻击。

Google SQL 注入或阅读here。

【讨论】:

【参考方案5】:

除了 SQL 注入等,参数化查询在 SQL 服务器看来总是一样的。查询执行计划很可能会被缓存,因此如果您再次发送相同的查询,它将运行得更快。如果您在一个循环中多次运行相同的查询,或者您有许多客户端查询您的服务器,这将非常明显。

【讨论】:

以上是关于什么是将参数传递给 SQL,我为什么需要它?的主要内容,如果未能解决你的问题,请参考以下文章

如何将参数传递给SQL(Excel)中的查询

将值列表作为输入参数传递给 PL/SQL 过程

有没有办法将参数传递给Runnable? [复制]

将函数参数传递给 sql 查询

将参数传递给 oracle 脚本

通过批处理文件将 varchar 参数传递给 sql 文件