flawopen.com/SQL Injection в Java/MyBatis
MyBatis ${} и #{}: защита от SQL Injection
Представьте #{value} как защищённое поле подготовленного запроса: база получает данные. ${value} копирует текст в SQL до подготовки.
Связанные значения и текст SQL
<select id="getUser">
SELECT * FROM users
WHERE id = ${id}
</select>
// Raw substitution: the SQL text changes
<select id="getUser">
SELECT * FROM users
WHERE id = #{id}
</select>
// MyBatis creates a PreparedStatement parameter
Зачем MyBatis нужны обе записи
#{} связывает значение параметром JDBC PreparedStatement. Параметр не заменяет SQL-синтаксис — имя таблицы, столбца или направление сортировки. ${} подставляет текст напрямую без экранирования. Предпочитайте статические запросы или <choose>. Иначе выбирайте идентификатор целиком из серверного списка; не интерполируйте произвольный текст запроса.
Когда нужны динамические идентификаторы
Параметр не заменяет идентификатор. Для сортировки сопоставляйте выбор фиксированному SQL в коде сервера (или используйте <choose>). Не передавайте столбец, таблицу или ASC/DESC клиента прямо в ${}. Экранирование не делает произвольный фрагмент безопасным.
Проверка MyBatis mapper
rg -n -F '${' --glob '*.xml' --glob '*.java' .Частые вопросы
Да. Правила те же. ${column} в @Select вставляет текст напрямую; связывайте значения через #{value}, идентификаторы разрешайте списком.
Нет. Проверьте совпадения; SQL может собираться в другом месте. Добавьте проверки XML и аннотаций и тесты на фиксированные варианты сортировки.