【问题标题】:allowUnsafeRenegotiation, but still CertificateExceptionallowUnsafeRenegotiation,但仍然是 CertificateException
【发布时间】:2015-07-26 20:12:50
【问题描述】:

我尝试使用 SOAPConnection 调用 https,我已经指向 keystore 和 truststore 如下:

    System.setProperty("javax.net.ssl.keyStore", "C:/kei/tasks/MIP/Cert/ccc_acp.keystore");
    System.setProperty("javax.net.ssl.keyStorePassword", "password");
    System.setProperty("javax.net.ssl.trustStore", "C:/kei/tasks/MIP/Cert/trusteaistore.keystore");
    System.setProperty("javax.net.ssl.trustStorePassword", "password");
    System.setProperty("javax.net.debug", "all");

但我还是得到了

javax.net.ssl.SSLHandshakeException:java.security.cert.CertificateException:不存在主题替代名称

我谷歌并找到以下临时解决方案

System.setProperty( "sun.security.ssl.allowUnsafeRenegotiation", "true" );

但即使我将 allowUnsafeRenegotation 设置为 true,我仍然得到 ​​p>

javax.net.ssl.SSLHandshakeException:java.security.cert.CertificateException:不存在主题替代名称

我尝试使用 SOAPUI 5.1.3,并且优先使用> ssl,我设置了密钥库和密钥库密码(但没有设置信任库的地方),这次我可以通过 https 连接到我的目标服务器!

所以

1)为什么soapUI 5.1.3不需要设置truststore(只需要keystore),却依然可以连接到https服务器?

2) 为什么使用系统属性指向同一个密钥库,但我无法使用 SOAPConnection 连接到 https 服务器?

3) 为什么我将 allowUnsafeRenegotitation 系统属性设置为 true,但它似乎仍在检查公共证书。 https服务器,并返回CertificateException?

**********************于 2015 年 5 月 15 日编辑

我把代码贴在这里

public static void main(String args[]){ 
    System.setProperty("javax.net.ssl.keyStore", "C:/kei/tasks/MIP/Cert/ccc_acp.keystore");
    System.setProperty("javax.net.ssl.keyStorePassword", "password");
    MipCccSoapTest mipCccSoapTest = new MipCccSoapTest();
    mipCccSoapTest.testHttpConnection();        
}

private void testHttpConnection(){
    try{
        doTrustToCertificates();            
         URL url = new URL("https://10.7.3.43:9443/iboss/CustomerCareM1");
         HttpsURLConnection conn = (HttpsURLConnection)url.openConnection(); 
         HttpsURLConnection.getDefaultSSLSocketFactory();
         System.out.println("ResponseCoede ="+conn.getResponseCode());
    }catch(Exception ex){
        ex.printStackTrace();
    }
    System.exit(0);
    //end testing
}

// trusting all certificate 
 public void doTrustToCertificates() throws Exception {
    Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
    TrustManager[] trustAllCerts = new TrustManager[]{
            new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
                    return;
                }

                public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
                    return;
                }
            }
    };

    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    HostnameVerifier hv = new HostnameVerifier() {
        public boolean verify(String urlHostName, SSLSession session) {
            if (!urlHostName.equalsIgnoreCase(session.getPeerHost())) {
                System.out.println("Warning: URL host '" + urlHostName + "' is different to SSLSession host '" + session.getPeerHost() + "'.");
            }
            return true;
        }
    };
    HttpsURLConnection.setDefaultHostnameVerifier(hv);
}

我收到以下错误

javax.net.ssl.SSLHandshakeException:收到致命警报:handshake_failure 在 sun.security.ssl.Alerts.getSSLException(未知来源)

但是密钥库应该是正确的,因为我在 SOAPUI 5.1.3 中使用了相同的密钥库,可以成功调用服务器。

**************** 2015 年 5 月 18 日编辑 *************

我注释掉以下代码后

Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
    TrustManager[] trustAllCerts = new TrustManager[]{
            new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
                    return;
                }

                public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
                    return;
                }
            }
    };

    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

它现在可以连接到https服务器了。

【问题讨论】:

  • '不安全的重新协商'与证书无关。

标签: java ssl https


【解决方案1】:

javax.net.ssl.SSLHandshakeException:java.security.cert.CertificateException:不存在主题替代名称

这是服务器证书的问题。您需要通过添加具有正确信息的主题替代部分来修复它,以便可以成功验证它。它与信任链无关,因此无需更改 keyStore 或 trustStore 帮助。如果知道服务器 URL 或证书,可能会提供更多信息。

System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", "true");

这是 TLS 协议级别的事情,与证书验证无关。

如果您无法修复服务器证书,请参阅SSLHandshakeException: No subject alternative names present 了解可能的解决方法(在谷歌上搜索此错误消息时首先点击!)。

【讨论】:

  • 我现在可以通过调用 doTrustToCertificates() 函数摆脱“不存在主题替代名称”,但随后出现另一个错误“javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure at sun .security.ssl.Alerts.getSSLException(Unknown Source)”抛出,我在我编辑的问题中发布相关信息,因为很难在此处发表评论。
  • @user1169587:不幸的是,您似乎已经在您的代码中包含了您可以在 Internet 上找到的任何 hack,但不了解它的作用(禁用安全重新协商、禁用信任链、使用自定义主机名验证.. .)。基于此,尚不清楚您的代码实际上在做什么,这意味着实际上不可能提供帮助。我建议您从头开始,在客户端使用正确的默认验证,并在服务器上使用正确的证书(即受信任并匹配主机名),这样您就不需要在代码中使用任何变通方法。
  • 在实际情况下,我将向 HTTPS 服务器传递一个soap 消息,并期望从该服务器接收一个soap 消息。附加代码只是连接部分的精简版
  • 问题是你的代码充满了hacks(变通方法),它们可能会按预期工作,也可能会在一起使用时产生奇怪的效果。其中一些变通办法禁用了 TLS 应提供的安全性的基本部分。我不会帮助使这种糟糕的解决方法变得可靠,而是应该修复问题的原因(服务器证书)并使用默认的安全设置。顺便说一句,如果服务器证书是针对主机名的,您应该在 URL 中包含主机名而不是 IP。
  • 现在可以连接,因为我之前在 sc.init(...) 中错误地将 keyManager 设置为 null,我会尝试获取正确的证书。如果允许,谢谢
猜你喜欢
  • 1970-01-01
  • 2015-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 2020-01-08
  • 1970-01-01
相关资源
最近更新 更多