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

初学者:

在我对如何将数据插入SQL Server的问题的答案中 ,他提到了传递参数而不是像我现在所拥有的字符串连接。

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

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

谢谢。

编辑:

好的,这就是我得到的。 它似乎正确地更新了数据库,最终我将硬编码的int更改为标签的输入。 请确认我是如何做到这一点不容易受到任何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(); } } 

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

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

以下是一些可能的SQL注入攻击的良好示例:

SQL注入攻击示例

将参数传递给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集合来传递值。

它会保护你免受小Bobby桌子的伤害。

http://xkcd.com/327/

这是一个例子:

  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返回一个我可以访问的值。

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

Google SQL注入或在此处阅读。

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