Включить HTTPS с самозаверяющим сертификатом в Spring Boot 2.0

Я следую этот учебник, чтобы включить HTTPS в Spring Boot 2.0 с использованием самозаверяющего сертификата, просто для целей тестирования. Таким образом, этот учебник включает в себя следующие шаги:

1. Сгенерируйте хранилище ключей с помощью keytool.

keytool -genkey -alias tomcat
 -storetype PKCS12 -keyalg RSA -keysize 2048
 -keystore keystore.p12 -validity 3650

2. Включите HTTPS в Spring Boot, добавив некоторые свойства в файл application.properties.

server.port: 8443
server.ssl.key-store: keystore.p12
server.ssl.key-store-password: mypassword
server.ssl.keyStoreType: PKCS12
server.ssl.keyAlias: tomcat

3. Перенаправить HTTP на HTTPS (необязательно). Я проигнорировал эту часть.

Но когда я запускаю свое приложение, у меня возникает такая ошибка:

org.apache.catalina.LifecycleException: Failed to start component [Connector[HTTP/1.1-8443]]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) ~[tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.catalina.core.StandardService.addConnector(StandardService.java:225) ~[tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.addPreviouslyRemovedConnectors(TomcatWebServer.java:255) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start(TomcatWebServer.java:197) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.startWebServer(ServletWebServerApplicationContext.java:300) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh(ServletWebServerApplicationContext.java:162) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:552) [spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:388) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:327) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1246) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1234) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at epic.gwdg.restgraph.RestgraphApplication.main(RestgraphApplication.java:10) [classes/:na]
Caused by: org.apache.catalina.LifecycleException: Protocol handler start failed
    at org.apache.catalina.connector.Connector.startInternal(Connector.java:1021) ~[tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) ~[tomcat-embed-core-8.5.28.jar:8.5.28]
    ... 13 common frames omitted
Caused by: java.lang.IllegalArgumentException: Private key must be accompanied by certificate chain
    at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:116) ~[tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.tomcat.util.net.AbstractJsseEndpoint.initialiseSsl(AbstractJsseEndpoint.java:87) ~[tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:225) ~[tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.tomcat.util.net.AbstractEndpoint.start(AbstractEndpoint.java:1150) ~[tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.coyote.AbstractProtocol.start(AbstractProtocol.java:591) ~[tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.catalina.connector.Connector.startInternal(Connector.java:1018) ~[tomcat-embed-core-8.5.28.jar:8.5.28]
    ... 14 common frames omitted
Caused by: java.lang.IllegalArgumentException: Private key must be accompanied by certificate chain
    at java.base/java.security.KeyStore.setKeyEntry(KeyStore.java:1170) ~[na:na]
    at org.apache.tomcat.util.net.jsse.JSSEUtil.getKeyManagers(JSSEUtil.java:257) ~[tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:114) ~[tomcat-embed-core-8.5.28.jar:8.5.28]
    ... 19 common frames omitted

2018-03-16 16:42:30.917  INFO 970 --- [           main] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
2018-03-16 16:42:30.931  INFO 970 --- [           main] ConditionEvaluationReportLoggingListener : 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2018-03-16 16:42:30.933 ERROR 970 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

The Tomcat connector configured to listen on port 8443 failed to start. The port may already be in use or the connector may be misconfigured.

Action:

Verify the connector's configuration, identify and stop any process that's listening on port 8443, or configure this application to listen on another port.

2018-03-16 16:42:30.934  INFO 970 --- [           main] ConfigServletWebServerApplicationContext : Closing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@58ce9668: startup date [Fri Mar 16 16:42:26 CET 2018]; root of context hierarchy
2018-03-16 16:42:30.936  INFO 970 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown

Process finished with exit code 1

По сути, это сообщение:

Private key must be accompanied by certificate chain.

Это самозаверяющий сертификат, поэтому у него, конечно же, нет доверенной цепочки. Как я могу это исправить?

Вот мой текущий файл application.properties:

server.port=8443
server.ssl.enabled=true
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-password=123456
server.ssl.key-store-type=PKCS12
server.ssl.key-alias=tomcat

Спасибо большое за вашу помощь.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
20
0
23 401
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Ответ принят как подходящий

Проблема в том, что в вашем сгенерированном хранилище ключей у вас нет пары ключей, поэтому нет закрытого ключа, потому что вы используете параметр -genkey, вам нужно изменить его с помощью параметра -genkeypair:

-genkey generates a Secret Key whereas the -genkeypair generates a key pair (a public key and a private key).

Поэтому я думаю, что это должно сработать:

keytool -genkeypair -alias tomcat -storetype PKCS12 -keyalg RSA -keysize 2048  -keystore keystore.p12 -validity 3650

В вашей весенней конфигурации загрузки измените ":" на "=" и добавьте путь к вашему хранилищу ключей, я полагаю, что ваш keystore.p12 находится в папке ресурсов, поэтому:

server.ssl.key-store = classpath:keystore.p12
server.ssl.key-store-password = mypassword
server.ssl.key-store-type = PKCS12
server.ssl.key-alias = tomcat

Спасибо, но у меня все та же проблема :(

Triet Doan 16.03.2018 17:15

Я обновляю свой ответ, в настройках вашей пружины conf change ":" by " = " и добавляю путь к вашему хранилищу ключей для параметра "server.ssl.key-store"

e2rabi 16.03.2018 17:34

Фактически, я использую «=» и «путь к классам» в своей конфигурации. Я попробовал оба способа, но ошибка все еще существует ...

Triet Doan 16.03.2018 17:36

Я обновляю свой ответ снова, есть другая проблема, снова измените "server.ssl.keyStoreType" = PKCS12 на "server.ssl.key-store-type = PKCS12"

e2rabi 16.03.2018 17:40

Я только что обновил свой вопрос, чтобы добавить свою конфигурацию. Я заметил, что поле пароля должно быть key-store-password, как у вас. Поменял, работает !!! Вы можете обновить свой ответ (key-alias). Отмечу ваш ответ как правильный. Спасибо :)

Triet Doan 16.03.2018 20:45

Мое приложение не дает мне исключения, но через http браузер сообщает Bad Request This combination of host and port requires TLS, а через https говорит NET::ERR_CERT_AUTHORITY_INVALID. Что мне тогда делать?

tibotka 20.11.2020 16:21

Я также получал эту ужасную ошибку Private key must be accompanied by certificate chain в моем приложении Spring Boot со встроенным сервером Tomcat. Это делало меня безумный.

Оказывается, моей проблемой была простая опечатка:

@Override
public void customize(ConfigurableServletWebServerFactory server) {
    Ssl ssl = new Ssl();
    ssl.setEnabled(true);
    ssl.setKeyStore(keystoreFile);
    ssl.setKeyPassword(keystorePass); // << Should be `setKeyStorePassword` !!!!
    ssl.setKeyStoreType(keystoreType);
    ssl.setKeyAlias(keystoreAlias);

    server.setSsl(ssl);
    server.setPort(sslPort);
}

Таким образом, сообщение об ошибке бесполезно вообще в этом случае. Надеюсь, это поможет кому-то другому. Просто убедитесь, что вы поместили правильные пароли (ключ против хранилища ключей) в нужное место. Та же проблема может возникнуть при настройке на основе свойств - это зависит от того, с чем вы работаете.

У меня такая же проблема. Я внес изменения из 2-го ответа. Но проблема не исчезла. После всего, что я сделал, я просто включил свой сертификат keystore.p12 в pom.xml в разделе профили

    <profiles>
    <!-- DEVELOPMENT PROFILE -->
    <profile>
        <id>dev</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <build>
            <resources>
                <resource>
                    <directory>src/main/resources</directory>
                    <includes>
                        <include>application.properties</include>
                        <include>keystore.p12</include>
                        <include>data/**</include>
                    </includes>
                </resource>
            </resources>
        </build>
    </profile>
</profiles>

1. используйте "-genkeypair"

keytool -genkeypair -alias tomcat -storetype PKCS12 -keyalg RSA -keysize 2048  -keystore keystore.p12 -validity 3650
  1. измените "server.ssl.key-password" на "server.ssl.ключ-хранилище-пароль"

+1 за вторую часть. Я думаю, что в более поздней версии Springboot было некоторое переименование, но, к сожалению, сообщение об ошибке ничего не говорит о невозможности правильно прочитать пароль.

Aaron Cooley 21.02.2019 22:24

Вы допустили небольшую ошибку в файле application.properties. Пожалуйста измените

server.ssl.key-password=your_password

к

server.ssl.key-store-password=your_password

Тогда он будет работать нормально. Надеюсь, поможет! Спасибо!

Спасибо, только это изменение решило мою проблему. До сих пор не знаю, почему, потому что у меня была еще одна самозаверяющая сертификация, и с server.ssl.key-password=your_password работал ...

Renan Ribeiro 04.03.2021 19:44

Spring Boot 2.2.1.RELEASE

keytool -genkeypair -keystore myKeystore2.p12 -storetype PKCS12 -storepass 123456 -alias ks-localhost -keyalg RSA -keysize 2048 -validity 99999 -dname "CN=My SSL Certificate, OU=My Team, O=My Company, L=My City, ST=My State, C=SA" -ext san=dns:localhost,ip:127.0.0.1

application.yml

server:
  tomcat:
    accesslog:
      enabled: true
  ssl:
    key-store-type: PKCS12
    key-store: classpath:myKeystore.p12
    key-alias: ks-localhost
    enabled: true
    protocol: TLS
    key-store-password: 123456

У меня была аналогичная проблема, в моем случае мне не хватало trustAnchors в хранилище доверенных сертификатов.

Одно из решений - использовать встроенный java keytool, как описано в других ответах. Но есть даже самый простой подход с использованием графического интерфейса KeyStore Explorer, поэтому я объясню полные шаги с обоими инструментами.

1. Прежде всего, как описано в ответе, нам нужно включить SSL в файле application.properties:

# <======= SSL Security ===========>
# Keystore config
server.ssl.key-store-type=PKCS12
server.ssl.key-store-password=change_it!
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-alias=alias
server.ssl.enabled=true

# Trust Store Certificates
server.ssl.trust-store=classpath:trust_store.p12
server.ssl.trust-store-type=PKCS12
server.ssl.trust-store-password=07123e1f482356c415f684407
# <=====================>

Хранилище ключей - это контейнер пары открытый - закрытый ключ, который используется сервером для безопасного взаимодействия с клиентами. У клиента, конечно же, должен быть открытый ключ, чтобы иметь возможность общаться с сервером.

Trust Store - это просто контейнер для сертификатов. (Открытые ключи). В нашем случае он будет содержать только один сертификат, используемый сервером.

2.1 Создайте хранилище ключей с java keytool:

keytool -genkeypair -alias alias -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore keystore.p12 -validity 3650

2.2 Экспортируйте сертификат, чтобы мы могли использовать его для создания хранилища ключей Trust Store.

keytool -export -keystore keystore.p12 -alias alias -file certificate.cer

2.3 На этом шаге автоматически создается новое хранилище ключей с импортированным доверенным сертификатом. (Инструмент спросит у вас пароль для нового набора клавиш, и когда он спросит «Доверять этому сертификату?», Конечно, вы должны ввести «да»)

keytool -importcert -file certificate.cer -keystore trust_store.p12 -alias alias

Наконец, сохраните оба хранилища ключей в папке ресурсов вашего приложения Spring Boot (как показано в альтернативном подходе).

Альтернативный подход с KeyStore Explorer

2.1 Создайте хранилище ключей с помощью KeyStore Explorer, как показано на снимках экрана:

Затем сохраните хранилище ключей в папке ресурсов вашего приложения Spring Boot:

2.2 Теперь нам нужно создать хранилище доверенных сертификатов, которое может быть предоставлено клиенту, которому необходимо взаимодействовать с нашим сервером. Прежде всего извлеките цепочку сертификатов, созданную KeyStore Explorer, а затем создайте новое хранилище ключей, импортируя сертификат внутри него, как показано на снимках экрана:

Затем, чтобы создать наше хранилище доверенных сертификатов, нажмите «Создать новое хранилище ключей» в формате PKCS12, как на предыдущих шагах, нажмите красный значок «Импортировать доверенный сертификат», выберите сертификат, сохраненный на предыдущем шаге, и, наконец, сохраните хранилище ключей. внутри папки ресурсов, как мы это делали при создании первого хранилища ключей.

Теперь ваш сервер будет иметь возможность обмениваться данными с безопасностью SSL. Помните, что ваши клиенты должны быть настроены для загрузки созданного вами хранилища доверенных сертификатов.

Другие вопросы по теме