Инъекция SQL - это очень простой метод атаки, но он все еще очень распространен по сей день. Причина - не что иное, как: нет патча для глупых. Почему ты это говоришь? Давайте возьмем Java в качестве примера для иллюстрации:
Предположим, есть такая таблица в базе данных:
Пользователь таблицы (ID VARCHAR (20) Первичный ключ, имя VARCHAR (20), AGE VARCHAR (20));
Затем используйте JDBC, чтобы управлять таблицей:
Private String getNameByuserId (String userId) {connection conn = getConn (); // Получить строку подключения sql = "Выберите имя от пользователя, где id =" + userId; Подготовленное Statement PSTMT = CONN.PrePareStatement (SQL); Результаты rs = pstmt.executeupdate (); ......}Приведенный выше код часто используется некоторыми разработчиками. Представьте себе эту ситуацию, когда параметр передачи пользователя «3; Пользователь Drop Table;», выполненный оператор SQL выглядит следующим образом:
Выберите имя от пользователя, где id = 3; Пользовать таблица;
После того, как база данных составлена и выполнена, пользовательский таблица удаляется. Смотри, простая атака инъекции SQL действует! Это связано с тем, что приведенный выше код не соответствует спецификациям программирования.
Инъекция SQL не существует, когда мы программируем в соответствии со спецификациями. Это также первый способ избежать инъекции SQL: предварительные операторы, код заключается в следующем:
Connection conn = getConn (); // Получить строку подключения sql = "Выберите имя от пользователя, где id =?"; Подготовленное Statement PSTMT = CONN.PrePareStatement (SQL); pstmt.setString (1, userId); Результаты rs = pstmt.executeupdate (); ....
Почему в приведенном выше коде не существует инъекции SQL? Поскольку используются предварительные операторы, предварительно скомпилированный оператор будет компилировать «Выбрать имя от пользователя, где id =?» Заявление заранее при выполнении, поэтому при выполнении вам нужно заменить его только на пропущенные параметры? Заполнитель. Для первого случая, который не соответствует спецификациям, программа создаст операторы SQL, а затем компилирует их с контентом, передаваемым пользователем. Это именно то, что проблема.
В дополнение к использованию предварительно скомпилированных утверждений, существует второй способ избежать атак SQL -инъекций: хранимых процедур. Хранильная процедура - это набор операторов SQL, которые выполняют конкретные функции. После компиляции он хранится в базе данных. Пользователи могут выполнить его, вызывая сохраненные процедуры и предоставив параметры (если хранящаяся процедура имеет параметры), а также может избежать инъекционных атак SQL.
Соединение conn = getConn (); stmt = conn.preparecall ("{call name_from_user (?,?)}"); STMT.SetInt (1,2); stmt.registeroutparameter (2, types.varchar); stmt.execute (); String name = stmt.getString (2);Соответствующие сохраненные процедуры в приведенном выше коде следующие:
Используйте пользователя; DeLimiter // Создать процедуру name_from_user (in in user_id int, out out user_name varchar (20)) Начните выберите имя в user_name из пользователя, где id = user_id; end // delimiter;
Конечно, пользователи также могут провести проверку символов на передней части, что также является способом избежать инъекции SQL: например, для приведенного выше параметра пользователя пользователь привлек бы ошибку при проверке того, что полуколон включен.
Однако, по наиболее фундаментальной причине, атака инъекции SQL существует, поскольку приложение не использует минимальные разрешения при доступе к базе данных. Я так думаю, кажется, что все использовали корневую учетную запись для доступа к базе данных.
Так как же Mybatis избегает атак SQL -инъекций? Давайте используем пользователя таблицы выше в качестве примера:
Предположим, что файл Mapper:
<select id = "getNameByuserid" resultyTpe = "string"> select name от пользователя, где id = #{userId} </selet>Соответствующий файл Java:
public interface usermapper {string getNameByuserid (@param ("userid") string userid); }Вы можете видеть, что входной параметр является имидным типом строки. Когда мы передаем userid = "34; Drop Table User;" Печатное заявление выглядит следующим образом:
Выберите имя от пользователя, где идентификатор =?
Независимо от того, какой пользователь введен, его заявления SQL такие. Это связано с использованием предварительно скомпилированных утверждений в базовой реализации. Когда база данных выполняет этот оператор, она напрямую использует предварительно скомпилированный оператор, а затем заменяет заполнителя на пропущенное пользовательское ирид? Просто беги. Не существует, чтобы сначала заменить заполнителя? Процесс компиляции проводится, поэтому нет места для выживания для инъекции SQL.
Так как же Mybatis достигает предварительной компиляции SQL? На самом деле, структура использует класс подготовленного Statatement. Класс подготовленных Staement не только избегает инъекции SQL, потому что он был предварительно сработал. Когда один и тот же оператор SQL выполняется n раз, он экономит время компиляции (N-1), тем самым повышая эффективность.
Если вы измените приведенное выше оператор на:
<select id = "getNameByUserid" resultType = "string"> выберите имя от пользователя, где id = $ {userId} </select> Когда мы введем userId="34;drop table user;" , печатное заявление выглядит следующим образом:
Выберите имя от пользователя, где id = 34; Drop Table User;
В настоящее время Mybatis не использует предварительные заявления. Сначала он выполнит строки, а затем выполнит компиляцию. Этот процесс является процессом вступления в силу инъекции SQL.
Поэтому при написании операторов отображения Mybatis попробуйте использовать формат «#{xxx}». Если вам нужно использовать параметры, такие как «$ {xxx}», вы должны вручную выполнять хорошую работу по фильтрации, чтобы предотвратить атаки впрыска SQL.
Суммировать
Выше приведено подробное объяснение метода предотвращения инъекции SQL Mybatis, введенным вам. Я надеюсь, что это будет полезно для вас. Если у вас есть какие -либо вопросы, пожалуйста, оставьте мне сообщение, и редактор ответит вам вовремя. Большое спасибо за вашу поддержку сайту wulin.com!