在调用 Web 服务时信任过期的自签名证书

Posted

技术标签:

【中文标题】在调用 Web 服务时信任过期的自签名证书【英文标题】:Trusting an expired self-signed certificate while calling a webservice 【发布时间】:2015-09-19 19:41:09 【问题描述】:

有一个受证书保护的网络服务。在调用它的客户端代码中,证书的 CA 必须存在于信任库 (JRE_path\lib\security\cacerts) 中 - 如果没有,您会在客户端获得 PKIX 异常。

如果证书过期会发生什么 - 客户端代码失败。

但是,可以通过将证书直接添加到信任库中来绕过这一点 - Trusting an expired certificate

即如果证书本身而不是 CA 存在于信任库中,那么即使证书已过期,一切正常。

在我的场景中,网络服务证书是自签名的,所以无论如何我都必须将它添加到信任库中,即使证书已过期,客户端也能继续正常工作。

现在我的问题是这是否适用于所有场景 - 我的程序只是一个运行本地 JRE 的命令行程序。

如果有应用程序调用 web 服务并且应用程序在 Websphere、JBoss、WebLogic、Tomcat、Glassfish 等上运行,并且自签名证书被添加到该环境的信任库中,我仍然可以假设它将继续工作(不给出过期错误)?

我认为它会起作用 - 因为那些应用程序服务器也会像任何程序一样使用 JRE - 还是我遗漏了什么?

【问题讨论】:

如果您不希望它安全,请不要使用 HTTPS。如果您确实希望它安全,请不要尝试挑选您自己的安全功能。 就像@EJP 所说:削弱安全性通常不是一个好主意。但作为程序员,我们通常也必须防止应用程序静默失败。因此,您应该确保如果程序失败,任何调查此问题的管理员都会清楚原因,或者您可以尝试捕获过期证书发生的异常或从代码内部强制接受哪些证书:***.com/questions/6659360/… 如果您的环境中有 openssl 命令(安装它)。您可以将其用作带有date check 的后台cmd 后台应用程序并读取结果 @AliHelmy 这有什么帮助? 【参考方案1】:

您可以通过以下代码绕过所有证书

try 
            TrustManager[] trustAllCerts = new TrustManager[]  new X509TrustManager() 
                public java.security.cert.X509Certificate[] getAcceptedIssuers() 
                    return null;
                

                public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) 
                

                public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) 
                
             ;
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());

            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
            HostnameVerifier allHostsValid = new HostnameVerifier() 
                public boolean verify(String hostname, SSLSession session) 
                    return true;
                
            ;
            SSLContext.setDefault(sc);
            HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
            LOGGER.debug("All Certificates Have Been Trusted Successfully.");
         catch (KeyManagementException ex) 
            LOGGER.error("Error:",ex);
         catch (NoSuchAlgorithmException ex) 
            LOGGER.error("Error:",ex);
         

【讨论】:

我知道这一点。然而,这不是我想要的。 你能澄清更多你想要什么 我想知道如果自签名证书存在于信任库中,自签名证书的到期是否总是被忽略 这不会“绕过所有证书”。它只是信任所有证书。 OP 需要删除在调用之前发生的过期检查。而且是不安全的。 @user93353 不,总是检查过期和有效性。 @EJP - 我不需要任何删除过期检查的代码。我只需要知道如果信任库中存在自签名证书,是否会忽略到期检查。我检查了一个命令行程序和 java 信任库,它被忽略了。我想知道它是否也被 Websphere、Weblogic 和其他流行的应用服务器忽略了【参考方案2】:

回答您的问题:“如果我将自签名证书添加到信任存储区,证书在过期后是否仍受信任 - 还是会引发异常?”

它仍然是受信任的(至少在 java 的 cacerts 信任存储中)。见https://softwareengineering.stackexchange.com/a/308538

【讨论】:

以上是关于在调用 Web 服务时信任过期的自签名证书的主要内容,如果未能解决你的问题,请参考以下文章

在 Windows 7 上信任 Java 7 的自签名证书

信任来自 IIS 的自签名证书

自签名证书。底层连接已关闭:无法建立信任关系

验证设备的自签名证书

如何信任 Android 上的自签名证书?

Openssl:错误“证书链中的自签名证书”