Java SSLPeerUnverifiedException:对等方未使用有效证书进行身份验证

Java SSLPeerUnverifiedException:对等方未使用有效证书进行身份验证,java,ssl,apache-httpclient-4.x,Java,Ssl,Apache Httpclient 4.x,我有Geo Trust签署的https证书。所有浏览器都能很好地打开我的网站。我的应用程序通过https授权,大部分时间一切正常。但有时用户无法连接并出现错误: javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated at sun.security.ssl.SSLSessionImpl.getPeerCertificates(Unknown Source) at org.apache.http.conn.ssl.Abstr

我有Geo Trust签署的https证书。所有浏览器都能很好地打开我的网站。我的应用程序通过https授权,大部分时间一切正常。但有时用户无法连接并出现错误:

javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
at sun.security.ssl.SSLSessionImpl.getPeerCertificates(Unknown Source)
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:126)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:572)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:294)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:645)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:480)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:784)
at org.greencubes.downloader.Downloader.downloadFile(Unknown Source)
at org.greencubes.lil.Launcher.<init>(Unknown Source)
at org.greencubes.lil.Launcher.main(Unknown Source)
javax.net.ssl.SSLPeerUnverifiedException:对等未经身份验证
位于sun.security.ssl.SSLSessionImpl.getPeerCertificates(未知源)
位于org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:126)
位于org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:572)
位于org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)
位于org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:294)
位于org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:645)
位于org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:480)
位于org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
位于org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
位于org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:784)
位于org.greencubes.downloader.downloader.downloadFile(未知源)
位于org.greencubes.lil.Launcher。(未知来源)
位于org.greencubes.lil.Launcher.main(未知来源)
最后一个用户使用的是Windows7x86和Java1.7u45u。它发生在随机的OSs和随机的java更新上,我不知道原因。有时它不会发生,但通常情况下,若用户有这样的错误,并没有什么可以帮助

我无法将证书添加到用户的密钥库,因为这是用户应用程序


目标url是auth.greencubes.org(空响应必须返回403),您可以检查它。

因此,我在一个用户的帮助下发现了一个问题。问题在于Kaspersky Antivirus(或者可能是其他一些antiviruses/防火墙,ESET NOD可能是)通过替换SSL证书检查加密连接,并且默认java密钥库没有Kaspersky CA证书(因为它是在安装Antivirus时生成的)

第一种解决方案是禁用检查加密连接或检查连接(web防病毒功能)或禁用防病毒

正确的解决方案是尝试使用Windows的密钥库,其中Antiviruses的CA证书是由antivirus本身添加的。可以通过设置JVM参数来完成:

-Djavax.net.ssl.trustStoreType=Windows-ROOT
(它必须是“Windows根目录”,而不是“Windows我的”!)

或者在应用程序启动时执行此代码(最好在main()函数中):

您只需要确保它是windows系统,所以命令行参数不是通用的解决方案

此代码可用于确保windows密钥存储存在且有效:

if(System.getProperty("os.name").toLowerCase().contains("windows")) {
    try {
        KeyStore ks = KeyStore.getInstance("Windows-ROOT");
        ks.load(null, null);
        System.setProperty("javax.net.ssl.trustStoreType", "Windows-ROOT");
    } catch(Exception e) {
        // Ignore: windows keystore is bad, left default
    }
}
if(System.getProperty("os.name").toLowerCase().contains("windows")) {
    try {
        KeyStore ks = KeyStore.getInstance("Windows-ROOT");
        ks.load(null, null);
        System.setProperty("javax.net.ssl.trustStoreType", "Windows-ROOT");
    } catch(Exception e) {
        // Ignore: windows keystore is bad, left default
    }
}