Создание безопасных операторов SQL в виде строк

Я использую C# и .NET 3.5. Мне нужно сгенерировать и сохранить некоторые операторы вставки T-SQL, которые будут выполняться позже на удаленном сервере.

Например, у меня есть массив сотрудников:

new Employee[]
{
   new Employee { ID = 5, Name = "Frank Grimes" },
   new Employee { ID = 6, Name = "Tim O'Reilly" }
}

и мне нужно получить массив строк, например:

"INSERT INTO Employees (id, name) VALUES (5, 'Frank Grimes')",
"INSERT INTO Employees (id, name) VALUES (6, 'Tim O''Reilly')"

Я смотрю на код, который создает операторы вставки с помощью String.Format, но мне кажется, что это неправильно. Я рассматривал возможность использования SqlCommand (надеясь сделать что-то вроде этого), но он не предлагает способа комбинировать текст команды с параметрами.

Достаточно ли просто заменить одинарные кавычки и построить строку?

string.Format("INSERT INTO Employees (id, name) VALUES ({0}, '{1}')",
    employee.ID,
    replaceQuotes(employee.Name)
    );

О чем я должен беспокоиться при этом? Исходные данные достаточно безопасны, но я не хочу делать слишком много предположений.

Обновлено: просто хочу указать, что в этом случае у меня нет SqlConnection или какого-либо способа напрямую подключиться к SQL Server. Это конкретное приложение должно генерировать операторы sql и ставить их в очередь для выполнения в другом месте - в противном случае я бы использовал SqlCommand.Parameters.AddWithValue ()

AddWithValue великолепен (я часто использую его), НО он может страдать от неправильного неявного преобразования типов, если не использовать его осторожно.

Mitch Wheat 16.11.2008 03:30
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
11
1
27 650
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Ответ принят как подходящий

Используйте параметризованные команды. Также передайте параметры вашему удаленному серверу и заставьте его вызывать SQL Server, сохраняя при этом различие между самим SQL и значениями параметров.

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

На самом деле, сейчас просто ложусь спать. Проповедь завтра утром с 10.30 до 11.30, так что тогда вам гарантирован хороший удар кнутом! ;)

Jon Skeet 16.11.2008 03:21

Проповедовать? Есть записи?

tofutim 31.01.2014 01:58

@tofutim: Я не знаю.

Jon Skeet 31.01.2014 01:59

Кажется, это не дает решения, когда жесткое требование, чтобы на выходе был файл сценария .sql с готовыми командами INSERT с данными, которые нужно вставить.

O. R. Mapper 08.05.2017 16:02

@ O.R.Mapper: Действительно - обратите внимание, что OP добавил это требование после того, как я ответил, хотя они все же приняли мой ответ, как ни странно ...

Jon Skeet 08.05.2017 17:00

@JonSkeet: Верно - вероятно, подходит для OP, но несколько раздражает будущих посетителей, которые действительно сталкиваются с проблемой, как описано в вопросе.

O. R. Mapper 08.05.2017 17:05

Создайте свой объект SqlCommand следующим образом:

SqlCommand cmd = new SqlCommand(
        "INSERT INTO Employees (id, name) VALUES (@id, @name)", conn);

SqlParameter param  = new SqlParameter();
param.ParameterName = "@id";
param.Value         = employee.ID;

cmd.Parameters.Add(param);

param  = new SqlParameter();
param.ParameterName = "@name";
param.Value         = employee.Name;

cmd.Parameters.Add(param);

cmd.ExecuteNonQuery();

Использование "cmd.AddWithValue (" @ id ", employee.ID);" намного короче.

Brad Wilson 16.11.2008 05:25

Я получаю это время от времени и получил это в своем ответе на этот.

Cade Roux 06.10.2010 04:11

Брэд Уилсон: Требуются дополнительные параметры: cmd.Parameters.AddWithValue("@id", employee.ID);.

Csaba Toth 29.03.2013 04:20

Как это отвечает на вопрос? OP четко заявляет, что у них нет доступа к БД, и вместо этого им нужно выводить команды, которые можно запустить позже.

O. R. Mapper 08.05.2017 16:03

Чтобы избежать внедрения, вам необходимо отправить данные на удаленный сервер (возможно, в XML), а затем на удаленный сервер данные должны быть преобразованы обратно в соответствующие типы данных и использоваться в параметризованных запросах или сохраненных процессах.

Хм, я согласен со всеми, что вы должны использовать параметризованные запросы, и оставим все как есть. Но как вы собираетесь передавать эти SQL-запросы на удаленный сервер? Есть ли у вас какой-либо тип службы, такой как веб-служба, которая будет принимать и выполнять произвольные команды Sql, или ваше клиентское приложение будет напрямую обращаться к БД?

Если вы используете какой-то прокси-сервер, то независимо от того, насколько вы дезинфицируете свои данные на клиенте, хакер может просто обойти ваше приложение и обратиться к сервису. В этом случае сделайте то, что рекомендует Cade, и передайте данные, например, как XML или в любом другом формате, который вы выберете (JSON, двоичный и т. д.). Затем создайте свой SQL прямо перед тем, как вы действительно запустите команду.

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

void string replaceQuotes(string value) {
     string tmp = value;
     tmp = tmp.Replace("'", "''");
     return tmp;
}

Ваше здоровье!

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

Karel Frajták 21.05.2013 14:22

@ KarelFrajták: Как можно использовать параметры, если отформатированные команды будут выполняться только позже (предположительно, после завершения выполнения кода C#), как описано в вопросе?

O. R. Mapper 08.05.2017 16:05

@ O.R.Mapper, в этом случае я бы поставил в очередь операторы и словарь с именами и значениями параметров.

Karel Frajták 16.05.2017 11:47

Другие вопросы по теме