线程“主”javax.net.ssl.SSLHandshakeException 中的异常:sun.security.validator.ValidatorException:未找到受信任的证书

Posted

技术标签:

【中文标题】线程“主”javax.net.ssl.SSLHandshakeException 中的异常:sun.security.validator.ValidatorException:未找到受信任的证书【英文标题】:Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: No trusted certificate found 【发布时间】:2015-01-15 18:33:58 【问题描述】:

我在自动化测试方面名列前茅。因此,我的任务是为 API 测试创建自动化脚本。我需要使用自签名序列创建 https 请求。该证书为我们的管理员提供了 p12 扩展名和密码文件。我将此证书导出为 .cer 扩展名。然后我创建了信任存储并将此证书导入此存储。

C:\Program Files (x86)\Java\jdk1.8.0_25\jre\bin>keytool -import -keystore clienttrust.jks -file marta.cer -storepass storepass

我在我的项目附近找到了 marta.cer 和 clienttrust.jks。我在 Java 上的 IntelliJ IDEA 13.1.1 中编写了我的代码。

代码如下:

public void testSimpleHttpsClient() throws CertificateException, InterruptedException, UnrecoverableKeyException, NoSuchAlgorithmException,
        IOException, KeyManagementException, KeyStoreException 


    URL url = new URL("https://intstg1-kaakioskpublicapi.ptstaging.ptec/TLE/36171/player/info");

    HttpsURLConnection con = (HttpsURLConnection)url.openConnection();
    con.setRequestMethod( "GET" );

    SSLContext sslContext = SSLContext.getInstance("TLS");

    char[]  passphrase = "storepass".toCharArray();
    KeyStore ks = KeyStore.getInstance("JKS");
    ks.load(this.getClass().getResourceAsStream("clienttrust.jks"), passphrase);
    System.out.println(ks);

    TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
    tmf.init(ks);

    System.out.println(tmf.toString());

    HostnameVerifier hostnameVerifier = new HostnameVerifier() 

        public boolean verify(String s, SSLSession sslSession) 
            return s.equals(sslSession.getPeerHost());
        
    ;
    con.setHostnameVerifier(hostnameVerifier);

    sslContext.init(null, tmf.getTrustManagers(), null);
   con.setSSLSocketFactory(sslContext.getSocketFactory());

    int responseCode = con.getResponseCode();
    InputStream inputStream;
    if (responseCode == HttpURLConnection.HTTP_OK) 
        inputStream = con.getInputStream();
     else 
        inputStream = con.getErrorStream();
    

    // Process the response
    BufferedReader reader;
    String line = null;
    reader = new BufferedReader( new InputStreamReader( inputStream ) );
    while( ( line = reader.readLine() ) != null )
    
        System.out.println( line );
    

    inputStream.close();

所以,在这段代码执行之后,我得到了下一个异常:

在 sun.security.ssl.Alerts.getSSLException(Alerts.java:192) 在 sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1917) 在 sun.security.ssl.Handshaker.fatalSE(Handshaker.java:301) 在 sun.security.ssl.Handshaker.fatalSE(Handshaker.java:295) 在 sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1471) 在 sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:212) 在 sun.security.ssl.Handshaker.processLoop(Handshaker.java:936) 在 sun.security.ssl.Handshaker.process_record(Handshaker.java:871) 在 sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1043) 在 sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1343) 在 sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1371) 在 sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1355) 在 sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563) 在 sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185) 在 sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1511) 在 sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1439) 在 java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480) 在 sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:338) 在 httpConnection.Connection.testSimpleHttpsClient(Connection.java:179) 在 httpConnection.Connection.main(Connection.java:22) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:483) 在 com.intellij.rt.execution.application.AppMain.main(AppMain.java:120) 原因:sun.security.validator.ValidatorException:未找到受信任的证书 在 sun.security.validator.SimpleValidator.buildTrustedChain(SimpleValidator.java:384) 在 sun.security.validator.SimpleValidator.engineValidate(SimpleValidator.java:133) 在 sun.security.validator.Validator.validate(Validator.java:260) 在 sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324) 在 sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229) 在 sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124) 在 sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1453) ... 20 更多

各位,请给我解释一下如何解决这个问题。

【问题讨论】:

看看here Ankur-singhal,感谢您的建议。我有一个问题要问你。我的证书的条目类型是“trustedCertEntry”,但在您的文章中 - 条目类型:PrivateKeyEntry。 “条目类型”非常重要吗? 您使用的HostnameVerifier 不安全。它只是根据反向查找检查主机名(很容易受到 MITM 攻击),而不是证书。 【参考方案1】:

将服务器证书导入为受信任

keytool -import -trustcacerts -alias somealias -keystore clienttrust.jks -file marta.cer

【讨论】:

以上是关于线程“主”javax.net.ssl.SSLHandshakeException 中的异常:sun.security.validator.ValidatorException:未找到受信任的证书的主要内容,如果未能解决你的问题,请参考以下文章

主线程怎么给子线程发送消息

主线程啥都没做,就会等待子线程结束。这是为啥?

Android 异步操作Android 线程切换 ( 判定当前线程是否是主线程 | 子线程中执行主线程方法 | 主线程中执行子线程方法 )

子线程怎么不阻塞主线程

QT中UI主窗口如何与子线程相互传递参数

java 子线程 回调 主线程