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