java.security.cert.Исключение CertificateException: не найдено имени, соответствующего локальному хосту

#java #ssl

#java #ssl

Вопрос:

В моем веб-приложении, когда оно пытается отправить HTTP-запрос самому себе, я получаю это исключение

 javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching localhost found
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
    at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1946)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:316)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:310)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1639)
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:223)
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1037)
    at sun.security.ssl.Handshaker.process_record(Handshaker.java:965)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1064)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1367)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1395)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1379)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1570)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1498)
    at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:352)
    at com.smcc.od.common.capi.OdCommonHelper.processHttpURLConnection(OdCommonHelper.java:593)
    at com.smcc.od.common.pipelet.http.ProcessHttpURLConnection.execute(ProcessHttpURLConnection.java:113)
    at com.intershop.beehive.core.internal.pipeline.PipeletNode.executeNode(PipeletNode.java:346)
    at com.intershop.beehive.core.internal.pipeline.Pipeline.executeNode(Pipeline.java:1116)
    at com.intershop.beehive.core.internal.pipeline.Pipeline.executePipeline(Pipeline.java:944)
    at com.intershop.beehive.core.internal.pipeline.PipelineProcessorImpl.executePipeline(PipelineProcessorImpl.java:641)
    at com.intershop.beehive.core.internal.pipeline.PipelineProcessorImpl.executePipeline(PipelineProcessorImpl.java:484)
    at com.intershop.beehive.pipeline.internal.PipelineEngineImpl.executePipeline(PipelineEngineImpl.java:97)
    at com.intershop.beehive.core.internal.pipeline.PipelineProcessorImpl.executePipeline(PipelineProcessorImpl.java:421)
    at com.intershop.beehive.core.internal.pipeline.PipelineProcessorImpl.executePipeline(PipelineProcessorImpl.java:250)
    at com.intershop.beehive.core.pipelet.pipeline.ExecutePipeline$PipelineExecutor.run(ExecutePipeline.java:440)
    at com.intershop.beehive.core.internal.execute.ExecutorServiceImpl$ClosingCurrentResourcesRunnable.run(ExecutorServiceImpl.java:176)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.security.cert.CertificateException: No name matching localhost found
    at sun.security.util.HostnameChecker.matchDNS(HostnameChecker.java:231)
    at sun.security.util.HostnameChecker.match(HostnameChecker.java:96)
    at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:462)
    at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:442)
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:209)
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:132)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1621)
    ... 28 common frames omitted
  

Вызываемый URL-адрес выглядит примерно так https://localhost:448/foo/bar .

В поисках решения я попытался создать самозаверяющий сертификат HTTPS и импортировать его в хранилище ключей моей JRE.

Я выполнил эту команду через Powershell, чтобы создать самозаверяющий сертификат для localhost :

 New-SelfSignedCertificate -CertStoreLocation Cert:LocalMachineMy -DnsName "localhost" -FriendlyName "localhost" -NotAfter (Get-Date).AddYears(10)
  

Затем я скопировал этот сертификат в раздел доверенных корневых центров сертификации. Я экспортировал его в .cer через MMC-файл и импортировал его в свою JRE с помощью команды

 amp; 'C:Program FilesAdoptOpenJDKjdk-8.0.222.10-hotspotbinkeytool.exe' -importcert -file D:tempcertificatelocalhost.cer -keystore 'C:Program FilesAdoptOpenJDKjdk-8.0.222.10-hotspotjrelibsecuritycacerts' -alias "localhost"
  

который вернул

 Certificate was added to keystore
  

Я перезапустил свой сервер приложений и снова попытался выполнить этот HTTP-запрос, но все равно получил исключение SSLException.

Я проверил, действительно ли сертификат был импортирован в JRE, и это:

 amp; 'C:Program FilesAdoptOpenJDKjdk-8.0.222.10-hotspotbinkeytool.exe' -keystore 'C:Program FilesAdoptOpenJDKjdk-8.0.222.10-hotspotjrelibsecuritycacerts' -list | Select-String "localhost"
  

который вернул

 localhost, Oct 28, 2020, trustedCertEntry,
  

Я не могу добавить пользовательскую javax.net.ssl.HostnameVerifier реализацию, чтобы пропустить localhost проверку. Есть ли какая-то конфигурация, которую я пропускаю?

Моя локальная среда находится в Windows 10. Мой веб-сервер — Apache.

Комментарии:

1. Простое добавление случайного сертификата в хранилище доверия не поможет. Это должен быть тот же сертификат, который использует apache. И если это не только для разработки, это не сработает. Веб-сервер не должен отправлять запросы самому себе в первую очередь.