Почему конкатенация строк SQL плохая идея?

Я прочитал, что это плохая идея, чтобы объединить строки SQL так:

cmd.CommandText = "Insert INTO workers Values (" + User.Identity.Name + "," + WorkerName.Text + "," + GetUniqueWorkerKey() + ");";

Так что рекомендуемый способ:

cmd.CommandText = "Insert INTO workers Values (@Username, @WorkerName, @WorkerKey)";
cmd.Parameters.AddWithValue("@Username", User.Identity.Name);
cmd.Paramters.AddWithValue("@WorkerName", TheWorkerNameYouPassedToThisMethod);

Я избегаю конкатенации строк SQL с тех пор, как я читал об этом, но я никогда не знаю, почему это не так. Разве метод AddWithValue() в конечном итоге не выполнил бы такую ​​же конкатенацию строк за сценой?

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

Ответы

Ответ 1

Короткий ответ: построение запросов путем конкатенации строк обычно позволяет SQL-инъекцию.

Представьте, что кто-то пытается создать пользователя с именем "Bob, Joe, 12345); DROP TABLE workers; --". В итоге вы создаете запрос "Insert INTO workers Values(Bob, Joe, 12345); DROP TABLE workers; --name, 34345236);" Bye-bye database. SQL-инъекция также может привести к запросам, возвращающим данные, которых они не должны, например, таблицам паролей. Каждый раз, когда у вас есть SQL-инъекция, просто предположите, что вы разрешаете произвольным третьим сторонам выпустить произвольные команды в вашу базу данных.

Подход AddWithValue() называется "параметризованными запросами". Это приводит к генерированию очень похожих команд, но AddWithValue() заботится о любых странных вещах, таких как пробелы и кавычки, в значениях параметров, которые могут привести к тому, что ваша команда будет означать нечто иное, чем то, что вы хотите. Конечно, вы могли бы сделать это, ускользая вручную, но это может быть сложно сделать правильно. Это намного проще и безопаснее, чтобы библиотека обрабатывала его для вас.

Обязательный XKCD