Топ-100Безопасные запросы с PreparedStatement - CodOrbits
LogoCodOrbits

Раздел: JDBC

Научитесь подключаться к базам данных через JDBC, выполнять SQL-запросы и обрабатывать результаты в Java.

Все разделы
Иконка JDBC

Безопасные запросы с PreparedStatement

Last updated: 9 мая 2025 г.

Напрямую в запрос данные пользователя передавать нельзя! Это опасно. Пользователь может туда вставить любое sql выражение какое ему вздумается.

Это называется sql инъекцией. И в результате может, например, что-то изменить в базе или своровать данные.

PreparedStatementкак Statement, только безопаснее. Он добавляет методы для управления входными параметрами от пользователя.

Продемонстрируем пример SQL инъекции.

Пример программы:

1import java.sql.*;
2
3public class PrStatement {
4    public static void main(String[] args)
5        throws ClassNotFoundException, SQLException {
6        Class.forName("com.mysql.cj.jdbc.Driver");
7        Connection connection =
8            DriverManager.getConnection(
9                "jdbc:mysql://localhost/storage",
10                "root", "07998MSD");
11        Statement statement = connection.createStatement();
12
13        //Положим переменная ниже это данные от
14        //пользователя например которые он ввел
15        //в текстовое поле на странице и которые
16        //в результате пришли сюда в программу.
17        //Эта переменная будет передаваться в sql запрос.
18        String userInpData = "‘LOTR’ or name=’Book1′;";
19
20        //Ниже в запрос передается переменная userInpData
21        ResultSet resultSet = statement.executeQuery(
22            "SELECT * FROM books where name="+ userInpData);
23        //вредный вариант очевидно не безопасен.
24        //Так как пользователь прислал сюда не просто
25        //название книги, например LOTR, а целую часть
26        //SQL запроса и в итоге то что прислал
27        //пользователь сложиться с тем что в методе
28        //executeQuery и выполниться запрос:
29        //SELECT * FROM books where name=’LOTR’ or name=’Book1′;.
30        //который выведет две книги, а не одну как было
31        //по задумке программистом.
32
33        System.out.println("\nBooks:");
34        while (resultSet.next()) {
35            int id = resultSet.getInt("id");
36            String name = resultSet.getString("name");
37
38            System.out.println("\n================\n");
39            System.out.println("id: " + id);
40            System.out.println("name: " + name);
41        }
42
43        System.out.println("Closing connection and "
44            +"releasing resources…");
45        resultSet.close();
46        statement.close();
47        connection.close();
48    }
49}

Вывод:

Видим, что произошла инъекция SQL запроса пользователем в SQL запрос, который в методе executeQuery. Таким образом, вывелось две книги вместо одной, как задумывал программист.

Теперь продемонстрируем пример с PreparedStatement, который предотвращает SQL инъекции.

Пример программы:

1import java.sql.*;
2
3public class PrStatement {
4    public static void main(String[] args)
5        throws ClassNotFoundException, SQLException {
6        Class.forName("com.mysql.cj.jdbc.Driver");
7        Connection connection = DriverManager.getConnection(
8            "jdbc:mysql://localhost/storage",
9            "root", "07998MSD");
10
11        String userInpData = "‘LOTR’ or name=’Book1′;"
12
13        //Запрос теперь делаем с помощью PreparedStatement
14        PreparedStatement pstatement =
15            connection.prepareStatement(
16            "SELECT * FROM books where name = ?");
17
18        //В строке кода ниже первый параметр
19        //это порядковый номер вопросика
20        //в верхнем запросе, второй данные от пользователя,
21        //которые средствами PreparedStatement будут
22        //переданы в запрос на место этого вопросика
23        //уже безопасным образом.
24        pstatement.setString(1,userInpData);
25        //preparedstatement защищает нас от инъекций как
26        //бы пользователь не менял userInpData.
27        ResultSet presultSet = pstatement.executeQuery();
28
29        System.out.println("\nBooks:");
30        while (presultSet.next()) {
31            int id = presultSet.getInt("id");
32            String name = presultSet.getString("name");
33
34            System.out.println("\n——————–");
35            System.out.println("id: " + id);
36            System.out.println("name: " + name);
37        }
38
39        System.out.println("Closing connection and "
40            +"releasing resources…");
41        presultSet.close();
42        pstatement.close();
43        connection.close();
44    }
45}

Вывод:

Видим, что ничего не вывелось, то есть PreparedStatement предотвратил инъекцию.


Следующие уроки

Использование хранимых процедур в Java

14
мин.

Similar Articles Icon
Divider

Что такое HTML и зачем он нужен

10
мин.

Similar Articles Icon
Divider

Ключевые теги HTML

9
мин.

Similar Articles Icon