Что передают параметры SQL и зачем мне это нужно?

Начинающий здесь:

В этом ответе на мой вопрос о том, как вставлять данные в SQL Server, он упомянул параметры передачи, а не конкатенацию строк, как в настоящее время.

Это действительно необходимо для безопасности? Если да, то какие именно параметры проходят? Когда я google, я много разбираюсь в хранимых процедурах. Это то, чего я хочу, я еще не знаю о хранимых процедурах....

Если вы можете указать мне в правильном направлении, я был бы признателен.

Спасибо.

EDIT:

Хорошо, вот что я получил. Кажется, что он правильно обновляет базу данных, и в конце концов я изменю жестко закодированные ints на входы с метки. Пожалуйста, подтвердите, что, как я это сделал, не уязвим для каких-либо 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(); 


    }

}

Ответы

Ответ 1

Передача параметров SQL избавляет вас от необходимости создавать динамическую строку SQL.

Создание динамических операторов SQL - ОГРОМНЫЙ риск для безопасности, потому что люди могут вставлять свой собственный код SQL в ваше приложение, возможно, выполняя нежелательные команды против ваших данных.

Есть несколько хороших образцов возможных атак SQL Injection:

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, и мы использовали коллекцию Parameters объекта SqlCommand для передачи значения.

Ответ 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 возвращается со значением, к которому я могу получить доступ.

Ответ 5

Основная проблема с просто конкатенацией строк заключается в том, что она часто оставляет вас уязвимыми для атак SQL Injection.

Google SQL Injection или прочитайте здесь.

Ответ 6

В дополнение к SQL-инъекциям и тому подобному, параметризованные запросы всегда выглядят одинаково для SQL-сервера. Скорее всего, план выполнения запросов будет кэшироваться, поэтому, если вы снова отправите тот же запрос, он будет работать быстрее. Это было бы очень заметно, если бы вы выполняли один и тот же запрос много раз в цикле или у вас было много клиентов, которые запрашивали ваш сервер.