параметризованные запросы против внедрения SQL

c# asp.net

7090 просмотра

4 ответа

Я новичок в Asp.net, и я только начинаю работать с классами. Недавно я создал класс, который будет обрабатывать большинство моих запросов SQL для меня, чтобы мне не приходилось многократно создавать новые соединения для всех моих файлов.

Один из созданных мной методов принимает запрос SQL в качестве параметра и возвращает результат. Я знаю, что должен использовать параметризованные запросы, чтобы избежать SQL-инъекций. У меня вопрос, как я могу сделать это, когда я передаю запрос в виде строкового параметра?

Например, вот метод, который я буду вызывать:

public static DataTable SqlDataTable(string sql)
{
    using (SqlConnection conn = new SqlConnection(DatabaseConnectionString))
    {
        SqlCommand cmd = new SqlCommand(sql, conn);
        cmd.Connection.Open();
        DataTable TempTable = new DataTable();
        TempTable.Load(cmd.ExecuteReader());
        return TempTable;
    }
}

Итак, из другого файла я хотел бы использовать этот метод так:

DataTable dt = new DataTable();

dt = SqlComm.SqlDataTable("SELECT * FROM Users WHERE UserName='" + login.Text  + "' and Password='" + password.Text + "'");

if (dt.Rows.Count > 0)
{
   // do something if the query returns rows
}

Это работает, но все равно будет уязвимым для уколов, верно? Есть ли способ передать переменные в строку в качестве параметров? Я знаю, что могу сделать это, если я создаю новый объект SQLCommand для запроса и использую Parameters.AddWithValue, но я хотел, чтобы все мои команды SQL были в отдельном классе.

Автор: Cineno28 Источник Размещён: 12.11.2019 09:08

Ответы (4)


15 плюса

Решение

Это работает, но все равно будет уязвимым для уколов, верно?

Да, ваш код ужасно уязвим для инъекций SQL.

Я знаю, что должен использовать параметризованные запросы, чтобы избежать SQL-инъекций.

Ах, да, конечно.

У меня вопрос, как я могу сделать это, когда я передаю запрос в виде строкового параметра?

Вы просто не должны передавать запрос как строковый параметр. Вместо этого вы должны передать запрос как строковый параметр, содержащий заполнители и значения для этих заполнителей:

public static DataTable SqlDataTable(string sql, IDictionary<string, object> values)
{
    using (SqlConnection conn = new SqlConnection(DatabaseConnectionString))
    using (SqlCommand cmd = conn.CreateCommand())
    {
        conn.Open();
        cmd.CommandText = sql;
        foreach (KeyValuePair<string, object> item in values)
        {
            cmd.Parameters.AddWithValue("@" + item.Key, item.Value);
        }

        DataTable table = new DataTable();
        using (var reader = cmd.ExecuteReader())
        {
            table.Load(reader);
            return table;
        }
    }
}

и затем используйте вашу функцию следующим образом:

DataTable dt = SqlComm.SqlDataTable(
    "SELECT * FROM Users WHERE UserName = @UserName AND Password = @Password",
    new Dictionary<string, object>
    {
        { "UserName", login.Text },
        { "Password", password.Text },
    }
);

if (dt.Rows.Count > 0)
{
   // do something if the query returns rows
}
Автор: Darin Dimitrov Размещён: 07.07.2013 12:41

0 плюса

То, что вы пытаетесь сделать, имеет вполне логичный смысл, и я могу понять, почему вы пришли к этой реализации. Однако то, что вы пытаетесь сделать, очень опасно, и, будучи новичком в ASP.NET, вы можете не знать, что есть множество других доступных вам опций, которые делают управление вашими данными намного проще и намного безопаснее.

@iamkrillin намекнул на одну такую ​​технологию - Object Relational Mapping (ORM). Платформа .NET фактически имеет первоклассную поддержку ORM, называемой Entity Framework . Я полагаю, что причина, по которой он предложил вам взглянуть на ORM, заключается в том, что ваш дизайн в принципе очень похож на работу ORM. Это абстрактные классы, представляющие таблицы в вашей базе данных, которые можно легко запросить с помощью LINQ. Запросы LINQ автоматически параметризуются и освобождают вас от необходимости управлять безопасностью ваших запросов. Они генерируют SQL на лету (так же, как вы, когда вы передаете строки в ваш класс доступа к данным), и гораздо более гибки в способе возврата данных (массивы, списки, вы называете их).

Однако недостатком ORM является то, что у них довольно крутые кривые обучения. Более простой вариант (хотя и немного старше, чем EF) - использовать типизированные наборы данных. Типизированные наборы данных гораздо проще создать, чем стоящие ORM, и, как правило, их гораздо проще реализовать. Хотя они и не такие гибкие, как ORM, они выполняют именно то, что вы пытаетесь сделать, простым, безопасным и уже решенным способом. К счастью, когда ASP.NET впервые вышел на рынок, обучающие видео были в основном сфокусированы на типизированных наборах данных, и поэтому появились различные высококачественные бесплатные видео / учебные пособия, которые помогут вам быстро приступить к работе.

Автор: Daniel Szabo Размещён: 07.07.2013 05:01

0 плюса

Вы на правильном пути, и я действительно сделал то, что вы ищете для себя тоже. Однако вместо того, чтобы просто передать строку в вашу функцию, я передаю объект SQL-команды ... Таким образом, вы можете правильно построить все свои команды и параметры и затем сказать ... вот, иди, запусти это, это готов к работе Что-то вроде

public static DataTable SqlDataTable(SqlCommand cmd)
{
    using (SqlConnection conn = new SqlConnection(DatabaseConnectionString))
    {  
        cmd.Connection = conn;   // store your connection to the command object..
        cmd.Connection.Open();
        DataTable TempTable = new DataTable();
        TempTable.Load(cmd.ExecuteReader());
        return TempTable;
    }
}

public DataTable GetMyCustomers(string likeName)
{
    SqlCommand cmd = new SqlCommand();
    cmd.CommandText = "select * from SomeTable where LastName like "@someParm%";
    cmd.Parameters.Add( "whateverParm", likeName );  // don't have SQL with me now, guessing syntax

    // so now your SQL Command is all built with parameters and ready to go.
    return SqlDataTable( cmd );
}
Автор: DRapp Размещён: 07.07.2013 12:18

-3 плюса

Мое предложение: используйте Orm. Есть из чего выбрать дни

Автор: iamkrillin Размещён: 07.07.2013 04:08
Вопросы из категории :
32x32