Spring Boot: Jdbc javax.net.ssl.SSLException: закрытие входящего до получения close_notify партнера
В настоящее время я узнаю больше о реализации JDBC и использовании баз данных в веб-приложении Spring Boot, и я обнаружил следующую трассировку стека, написанную в нижней части поста.
Я создал простую модель Employee и пытаюсь выполнить некоторый код базы данных в том же классе, в котором лежит мой main(). Модель и основной класс - это только два java-файла, существующих во всем этом проекте. Я пытаюсь реализовать следующий код run(), который переопределяет код из интерфейса, CommandLineRunner, но я не получаю журналы, которые должны появляться после log.info("Часть A:"):
log.info("Part A:")
employees.forEach(employee -> {log.info(employee.toString());
log.info("part a");});
- Вещи, которые я заметил:
Я заметил, что последняя строка журнала перед запуском трассировки стека происходит от "Thread-1" вместо "main". Я думаю, это означает, что поток откуда-то, кроме основного, столкнулся с ошибкой и закрыл соединение до того, как он должен нормально закрыться.
Кроме того, я думаю, что, поскольку HikariPool закрылся до "peer close_notify", что, как я полагаю, относится к нормальному закрытию HikariPool, я не могу увидеть последний бит журнала, который я продолжал пытаться получить. Последнее, что я хочу увидеть - это регистрация сотрудника, который был вставлен в мою базу данных.
Последний фрагмент журнала, который я хочу увидеть, должен быть получен из этой строки кода:
employees.forEach(employee -> {log.info(employee.toString());
log.info("part a");});
- что следует отметить:
Из-за этой строки в журнале я думал, что увижу сотрудника, вставленного в мою базу данных, но когда я запросил непосредственно у клиента командной строки MySQL, он вернул пустой набор:
2018-11-03 21:08:35.362 INFO 2408 --- [ main] c.j.jdbctest1.JdbcTest1Application : rows affected: 1
Я не понимаю, почему строка пострадала, когда ничего не было вставлено в базу данных.
Трассировка стека и журналы: (Трассировка стека, вставленная ниже, на самом деле повторяется еще несколько раз, но для краткости я ее обрезал.)
2018-11-03 21:08:32.997 INFO 2408 --- [ main] c.j.jdbctest1.JdbcTest1Application : Starting JdbcTest1Application on KitKat with PID 2408 (C:\Users\Nano\Downloads\jdbc-test1\jdbc-test1\target\classes started by Nano in C:\Users\Nano\Downloads\jdbc-test1\jdbc-test1)
2018-11-03 21:08:33.003 INFO 2408 --- [ main] c.j.jdbctest1.JdbcTest1Application : No active profile set, falling back to default profiles: default
2018-11-03 21:08:33.770 INFO 2408 --- [ main] c.j.jdbctest1.JdbcTest1Application : Started JdbcTest1Application in 1.024 seconds (JVM running for 1.778)
2018-11-03 21:08:33.770 INFO 2408 --- [ main] c.j.jdbctest1.JdbcTest1Application : Creating tables
2018-11-03 21:08:33.770 INFO 2408 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2018-11-03 21:08:34.082 INFO 2408 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2018-11-03 21:08:35.135 INFO 2408 --- [ main] c.j.jdbctest1.JdbcTest1Application : Inserting Baggins Hopkins
2018-11-03 21:08:35.362 INFO 2408 --- [ main] c.j.jdbctest1.JdbcTest1Application : rows affected: 1
2018-11-03 21:08:35.362 INFO 2408 --- [ main] c.j.jdbctest1.JdbcTest1Application : Querying for employee
2018-11-03 21:08:36.065 INFO 2408 --- [ main] c.j.jdbctest1.JdbcTest1Application : Part A:
2018-11-03 21:08:36.065 INFO 2408 --- [ Thread-1] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
Sat Nov 03 21:08:36 KST 2018 WARN: Caught while disconnecting...
EXCEPTION STACK TRACE:
** BEGIN NESTED EXCEPTION **
javax.net.ssl.SSLException
MESSAGE: closing inbound before receiving peer's close_notify
STACKTRACE:
javax.net.ssl.SSLException: closing inbound before receiving peer's close_notify
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:129)
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:308)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:264)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:255)
at java.base/sun.security.ssl.SSLSocketImpl.shutdownInput(SSLSocketImpl.java:645)
at java.base/sun.security.ssl.SSLSocketImpl.shutdownInput(SSLSocketImpl.java:624)
at com.mysql.cj.protocol.a.NativeProtocol.quit(NativeProtocol.java:1312)
at com.mysql.cj.NativeSession.quit(NativeSession.java:182)
at com.mysql.cj.jdbc.ConnectionImpl.realClose(ConnectionImpl.java:1750)
at com.mysql.cj.jdbc.ConnectionImpl.close(ConnectionImpl.java:720)
at com.zaxxer.hikari.pool.PoolBase.quietlyCloseConnection(PoolBase.java:135)
at com.zaxxer.hikari.pool.HikariPool.lambda$closeConnection$1(HikariPool.java:441)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
** END NESTED EXCEPTION **
Код Java:
@SpringBootApplication
public class JdbcTest1Application implements CommandLineRunner {
private static final Logger log = LoggerFactory.getLogger(JdbcTest1Application.class);
@Autowired
JdbcTemplate jdbcTemplate;
public static void main(String[] args) {
SpringApplication.run(JdbcTest1Application.class, args);
}
@Override
public void run(String... args) throws Exception {
log.info("Creating tables");
jdbcTemplate.execute("DROP TABLE IF EXISTS employees");
jdbcTemplate.execute("CREATE TABLE employees (emp_id int, name varchar(100), role varchar(100), status varchar(100))");
log.info("Inserting Baggins Hopkins");
int rowsAffected = jdbcTemplate.update("INSERT INTO EMPLOYEE(EMP_ID, NAME, ROLE, STATUS)"
+ " VALUES(1,'Baggins Hopkins','thief','WORKING')");
log.info("rows affected: "+ Integer.toString(rowsAffected));
log.info("Querying for employee");
String sql = "SELECT emp_id,name,role,status FROM employees";
List<Employee> employees = jdbcTemplate.query(sql,(rs, rowNum)->
new Employee(rs.getInt("emp_id"), rs.getString("name"),
rs.getString("role"),Status.valueOf(rs.getString("status"))));
log.info("Part A:");
employees.forEach(employee -> {log.info(employee.toString());
log.info("part a");});
}
}
Также на всякий случай это имеет значение, я вставил этот код из application.properties:
spring.datasource.url=jdbc:mysql://localhost:3306/employee_database
spring.datasource.username=employee
spring.datasource.password=employee
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
14 ответов
Чтобы решить эту проблему, мне понадобилось около трех дней.
Сначала я решил эту проблему, пытаясь настроить собственный SSL для mysql, и потратил на это немало часов. Прошло слишком много времени, пока я не понял, что его настройка связана с Cmake и C++, что заставило меня сдаться. Это было очень сложно. Однако я не сдался и попытался полностью отключить SSL с помощью метода, который не был найден. И в конце концов я нашел метод. Вот:
- Вы должны использовать старый пароль для MySQL. Устаревший пароль - это способ аутентификации MySQL в версии 5.7x.
Снова откройте установщик MySQL и заново настройте параметры сервера MySQL. Когда вы попадете туда, вы увидите этот экран:
Экран, к которому вы должны добраться
Вы можете получить некоторые ошибки при достижении последней стадии реконфигурации:
У меня были проблемы на последнем этапе, я понятия не имел, как исправить, поэтому я полностью удалил MySQL. Я использую окна. Я удалил корневой каталог проекта MySQL из Program Files, чтобы удалить MySQL. Я также удалил базы данных, сохраненные в Program Data (скрытая папка на диске C), потому что я хотел начать заново (ВНИМАНИЕ: это удалит все ваши ранее сохраненные данные!). Удаление MySQL из панели управления может быть недостаточно для полного удаления MySQL с вашего компьютера.
- Удалите все файлы *.pem в C:\ProgramData\MySQL\MySQL Server 8.0\Data. (или переместить его куда-нибудь еще, что я и сделал)
Вы можете не увидеть ProgramData на диске C. Это потому, что это скрытая папка. Чтобы увидеть скрытые папки:
поиск параметров папки в панели управления.
Перейти к просмотру.
В разделе "Дополнительные настройки" и "Скрытые файлы и папки" нажмите "Показать скрытые файлы, папки и диски".
- Перейдите в C: \ ProgramData \ MySQL \ MySQL Server 8.0 и откройте my.cnf (или my.ini). Добавьте следующую строку после [mysqld]:
=0 SSL
Тогда сохраните. Это должно работать сейчас.
РЕДАКТИРОВАТЬ: я понял, что мой sql синтаксис для запроса на обновление был неправильным. Я вставил не в ту таблицу. Я думаю, что вставка в базу данных все еще работала независимо от того, исправила ли я проблему с SSLException или нет. (Я не уверен, хотя...)
Рекомендации:
Не удается установить SSL-соединение с базой данных, попробуйте изменить URL-адрес источника данных на:
spring.datasource.url=jdbc:mysql://localhost:3306/employee_database?useSSL=false
Предупреждение выглядит как ошибка драйвера MySQL с включенной Java 11 и SSL: https://bugs.mysql.com/bug.php?id=93590
Отключение шифрования из-за предупреждения водителя - плохая идея.
Ваша проблема вставки больше похожа на классическую проблему транзакции, хотя я сомневаюсь, что она связана с предупреждением SSL.
Это сработало для меня
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
<version>8.0.20</version>
</dependency>
Я также столкнулся с той же проблемой. если вы посмотрите на трассировку стека, ясно, что делать -
Sat Mar 16 09:00:01 IST 2019 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'.
You need either to explicitly disable SSL by setting **useSSL=false**, or set **useSSL=true** and provide truststore for server certificate verification.
поэтому после отключения ssl путем внесения изменений в источник данных url решил проблему -
spring.datasource.url=jdbc:mysql://localhost:3306/security?useSSL=false
Моя аналогичная проблема в коте, пытающемся подключиться через ssl к Aurora mysql (AWS)
Я решил проблему, обновив версию драйвера с mysql-connector-java-5.1.40.jar до mysql-connector-java-5.1.49.jar и установив корневой ЦС в ceacerts:
keytool -import -trustcacerts -file rds-ca-2019-root.pem -keystore /<your_java_home>/lib/security/cacerts
Надеюсь, ты пригодишься
Попробуйте использовать следующий URL. Как они предложили, используйте useSSL=false. Кроме того, не забудьте использовать <&> вместо просто &, если в вашем URL-адресе определено несколько свойств.
jdbc:mysql: // локальный:3306/TestDB?serverTimezone=PST и amp; useSSL=false
Я тоже столкнулся с той же проблемой
Но затем я обновил версию mysql-connector-java с 5.1.46 до 8.0.20 и изменив com.mysql.jdbc.Driver
к com.mysql.cj.jdbc.Driver
это решило мою проблему
Моя подобная проблема находится в искре, я решил проблему, опустив версию java от 'openjdk version "1.8.0_275"' до 'openjdk version "1.8.0_265"', надеюсь, вам пригодится
У меня возникла та же проблема с сервером приложений Wildfly, работающим на Temurin jdk8u362 с использованием mysql-connector-java-8.0.15 для подключения к MySQL 8, проблема исчезла после обновления до последних версий Temurin JDK 8 и Connector/J для дата (jdk8u372-b07, com.mysql.mysql-connector-j:8.0.33).
У меня была эта проблема, и я решил использовать решение Carrier Pigeon Protocol, пока случайно не решил ее, обновив Tomcat с версии 9.0.12 до 9.0.16.
Вместо того, чтобы отключать SSL/TLS, я добавил следующее к строке подключения к базе данных:&enabledTLSProtocols=TLSv1.2
Вызвано: javax.persistence.PersistenceException: [PersistenceUnit: name-unit] Невозможно построить Hibernate SessionFactory
У меня была точно такая же проблема, я также изменил false my useSSL, например, useSSL=false, и он отлично работает. Думаю, для тех, кто использует intelliJ Ultimate, проблемы с ошибкой не возникнет. Но для тех, кто использует версию сообщества, «да» также для тех, кто использует netbeans, как в моем случае. Это касается управления файлами persistence.xml и файлом EntityManagerHolder.
Я столкнулся с аналогичной проблемой, когда обновил версию Java на своем сервере до 11 с 8.
Spring boot начал поддерживать Java 11 начиная с версии 2.1 и новее. Поэтому убедитесь, что зависимости вашего проекта также обновлены соответствующим образом. Это актуально для этого ответа, поскольку SpringBoot также влияет на соединитель MySQL, ядро Hibernate и другие зависимости.
Невозможность подключения к БД приводила к еще нескольким ошибкам NoClassDefFoundErrors. Поэтому убедитесь, что вы решили эту проблему, прежде чем искать другие ошибки.
Пример зависимости pom для стартера SpringBoot
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.12.RELEASE</version>
<relativePath />
</parent>
Надеюсь, это кому-то поможет.