Spring Boot: Jdbc javax.net.ssl.SSLException: закрытие входящего до получения peer 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");});

--Things Я заметил:

Я заметил, что последняя строка журнала перед запуском трассировки стека происходит от "Thread-1" вместо "main". Я думаю, это означает, что поток откуда-то, кроме основного, столкнулся с ошибкой и закрыл соединение до того, как он должен нормально закрыться.

Кроме того, я думаю, что поскольку HikariPool закрылся до "peer close_notify", что, как я полагаю, относится к нормальному закрытию HikariPool, я не могу увидеть последний бит журналирования, который я продолжал пытаться получить. Последнее, что я хочу увидеть - это регистрация сотрудника, который был вставлен в мою базу данных.

Последний фрагмент журнала, который я хочу увидеть, должен быть получен из этой строки кода:

employees.forEach(employee -> {log.info(employee.toString());
        log.info("part a");});

--Things отметить:

Из-за этой строки в журнале я думал, что увижу сотрудника, вставленного в мою базу данных, но когда я запросил непосредственно у клиента командной строки 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 close_notify

STACKTRACE:

javax.net.ssl.SSLException: closing inbound before receiving peer 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

Ответ 1

Чтобы решить эту проблему, мне понадобилось около трех дней.

(Изменить. Это обходной путь для тестирования, а не решение.)

Сначала я решил эту проблему, пытаясь настроить собственный SSL для mysql, и потратил на это немало часов. Прошло слишком много времени, пока я не понял, что его настройка связана с Cmake и C++, что заставило меня сдаться. Это было очень сложно. Однако я не сдался и попытался полностью отключить SSL с помощью метода, который не был найден. И в конце концов я нашел метод. Вот оно:

  1. Вы должны использовать устаревший пароль для MySQL. Устаревший пароль - это способ аутентификации MySQL в версии 5.7x.

Снова откройте установщик MySQL и заново настройте параметры сервера MySQL. Когда вы попадете туда, вы увидите этот экран:

Экран, который вы должны получить на

При достижении финальной стадии реконфигурации могут появиться некоторые ошибки:

У меня были проблемы на последнем этапе, я понятия не имел, как исправить, поэтому я полностью удалил MySQL. Я использую окна. Я удалил корневой каталог проекта MySQL из Program Files, чтобы удалить MySQL. Я также удалил базы данных, сохраненные в Program Data (скрытая папка на диске C), потому что я хотел начать заново (ВНИМАНИЕ: это удалит все ваши ранее сохраненные данные!). Удаление MySQL из панели управления может быть недостаточно для полного удаления MySQL с вашего компьютера.

  1. Удалите все файлы *.pem в C:\ProgramData\MySQL\MySQL Server 8.0\Data. (или перенесите его куда-нибудь еще, что я и сделал)

Вы можете не увидеть ProgramData на диске C. Это потому, что это скрытая папка. Чтобы увидеть скрытые папки:

найдите параметры папки на панели управления.

Перейти к просмотру.

В разделе "Дополнительные параметры" и "Скрытые файлы и папки" нажмите "Показать скрытые файлы, папки и диски".

  1. Перейдите в C:\ProgramData\MySQL\MySQL Server 8.0 и откройте my.cnf (или my.ini). Добавьте следующую строку после [mysqld]:

ssl=0

Тогда сохраните. Это должно работать сейчас.

Рекомендации:

  1. https://community.atlassian.com/t5/Confluence-questions/MySQL-Public-Key-Retrieval-is-not-allowed/qaq-p/778956
  2. https://scalegrid.io/blog/configuring-and-managing-ssl-on-your-mysql-server/

Ответ 2

Не удается установить SSL-соединение с базой данных, попробуйте изменить URL-адрес источника данных на:

spring.datasource.url=jdbc:mysql://localhost:3306/employee_database?useSSL=false

Ответ 3

Предупреждение выглядит как ошибка драйвера MySQL с включенными Java 11 и SSL: https://bugs.mysql.com/bug.php?id=93590
Отключение шифрования из-за предупреждения водителя - плохая идея.

Ваша проблема вставки больше похожа на классическую проблему транзакции, хотя я сомневаюсь, что она связана с предупреждением SSL.

Ответ 4

Я также столкнулся с той же проблемой. если вы посмотрите на трассировку стека, ясно, что делать -

Sat Mar 16 09:00:01 IST 2019 WARN: Establishing SSL connection without server 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

Ответ 5

У меня возникла эта проблема, и я решил использовать решение протокола Carrier Pigeon, пока случайно не решил ее, обновив Tomcat с версии 9.0.12 до 9.0.16.