Какой самый простой способ исправить небезопасный SQL-запрос, построенный конкатенацией строк?

«Какой самый простой способ исправить небезопасный SQL-запрос, построенный конкатенацией строк?» — вопрос из категории Базы данных, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Самый простой и обязательный способ — заменить конкатенацию на PreparedStatement. Это мгновенно устраняет уязвимость к SQL-инъекциям и часто улучшает производительность.

До (опасный код):

String userId = request.getParameter("id");
// Уязвимость: если userId = "1; DROP TABLE users --", запрос выполнит удаление таблицы.
String sql = "SELECT * FROM users WHERE id = " + userId;
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sql);

После (безопасный код с PreparedStatement):

String userId = request.getParameter("id");
String sql = "SELECT * FROM users WHERE id = ?"; // Плейсхолдер '?'

PreparedStatement pstmt = connection.prepareStatement(sql);
// Параметр безопасно подставляется, инъекция невозможна.
pstmt.setString(1, userId); // Явное указание типа данных
ResultSet rs = pstmt.executeQuery();

Преимущества PreparedStatement:

  1. Безопасность: Параметры обрабатываются как данные, а не как часть SQL-команды.
  2. Производительность: Скомпилированный запрос может кешироваться СУБД при повторном использовании.
  3. Читаемость: Запрос легче читать и поддерживать.

Дополнительные шаги для сложных запросов:

  • Использовать ORM-фреймворк (JPA/Hibernate), который по умолчанию использует параметризованные запросы.
  • Проверить и оптимизировать индексы для условий в WHERE.
  • Воспользоваться встроенным валидатором SQL в IDE для исправления синтаксических ошибок.