本地主机上的SSL证书无法使用

3

我在使用Java代码访问https URL时遇到了异常。当我尝试访问时,会出现以下异常:

Caused by: 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:1949)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509)
        at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
        at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
        at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
        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.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:153)
        at org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpRequest.java:81)
        at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48)
        at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53)
        at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:569)
        ... 131 more
Caused by: java.security.cert.CertificateException: No name matching localhost found
        at sun.security.util.HostnameChecker.matchDNS(HostnameChecker.java:221)
        at sun.security.util.HostnameChecker.match(HostnameChecker.java:95)
        at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:455)
        at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:436)
        at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:200)
        at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1491)

我尝试使用以下命令生成SSL证书:
./jdk1.8/bin/keytool -genkey -keystore /srv/jakarta/.keystore -alias ALIAS \
    -keyalg RSA -keysize 4096 -validity 720
Enter keystore password: # well, enter something
Re-enter new password: # same as above
What is your first and last name?
  [Unknown]:  localhost # !!! IMPORTANT this is the domain name, NOT YOUR name
What is the name of your organizational unit?
  [Unknown]:  # enter something or leave empty
What is the name of your organization?
  [Unknown]:  # enter something or leave empty
What is the name of your City or Locality?
  [Unknown]:  # enter something or leave empty
What is the name of your State or Province?
  [Unknown]:  # enter something or leave empty
What is the two-letter country code for this unit?
  [Unknown]:  # enter something or leave empty
Is CN=example com, OU=Foo, O=Bar, L=City, ST=AA, C=FB correct?
  [no]:  yes
Enter key password for <lea-prod>
    (RETURN if same as keystore password): # Press RETURN

以下是Tomcat/ server.xml的配置:

 <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
       maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
       clientAuth="false" sslProtocol="TLS"
       keyAlias="ALIAS" keystoreFile="/srv/jakarta/.keystore"
       keystorePass="PW from step 1" />

然而,它仍然无法正常工作,我面临着相同的错误。 有没有办法解决这个问题? 谢谢。

你是否使用localhost访问URL?如果是,你的证书名称是localhost吗?你是否已将SSL证书添加为受信任的证书? - StefanE
是的,我可以直接在本地主机上访问URL,并且证书名称为localhost。我创建了一个本地密钥库而不是将其添加到Windows密钥库中。这样做是否使其受信任?我对此有一点想法。 - AppleBud
假设您正在从Java程序访问URL,则需要将证书添加为信任项到您的密钥库中。https://docs.oracle.com/javase/tutorial/security/toolsign/rstep2.html - StefanE
2个回答

4

错误信息的意思就是,你的证书是以 example.com 作为公共名称发放的。然而,在地址栏中你输入了 localhost 作为服务器名称。显然,这两个名称不匹配。因此,你应该将证书的公共名称(CN)也更改为 localhost,即像你已经做过的那样重新生成正确名称为 localhost 的证书。

接下来,你需要将证书导入浏览器的证书存储库中。但这是另一个话题。在你更正证书的公共名称后,异常就会消失。


那是我的错误,@Bjorn Zurmaar。我只将其命名为localhost并将其添加到本地生成的密钥库中,而不是Windows默认密钥库。但我没有通过浏览器访问URL,而是通过代码访问它们。 - AppleBud
无论您是通过浏览器还是执行其他代码来访问URL,这都不重要。如果有SSL握手,则证书的通用名称和主机名必须匹配。如果它们不匹配,则必须拒绝该证书。否则,您可以拥有一个有效证书并将其放置在任何服务器上,以使其看起来合法。 - Björn Zurmaar

0

我相信你正在尝试访问一个使用HTTPS协议托管的服务。在这种情况下,你需要获取网站/服务的证书,并将其添加到你的Java密钥库中。这是你在生产代码中应该使用证书的方式。

另外,你可以重写HostNameVerifier类来抑制任何错误,并在你的Java SSL上下文中进行设置以忽略任何错误。理想情况下,当测试代码或SSL证书不可用时,我们应该使用错误抑制。


网站在我的本地机器上。我想使用https访问一些URL,但仍然出现错误:sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:455)。 - AppleBud
在这种情况下,尝试覆盖SSLContext并设置虚拟TrustStore。 - Imtiyaz J

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接