1

我们有一个 Java 应用程序,我们需要忽略过期的自签名证书,但是我们无法修改代码来执行此操作。我想知道是否有我们可以在启动时提供的系统属性或环境变量,这将允许我们暂时忽略所有过期的证书,或者甚至更具体,并在外部提供我们希望过期的特定证书忽略。

有人有任何可行的想法吗?

4

1 回答 1

0

下面是结合java-ignore expired ssl certificate和Java SSL得到的解决方案:如何禁用主机名验证

public class IgnoreExpiredServerCertificateAgent {

    public static void premain(String args, Instrumentation inst) throws Exception {
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init((KeyStore) null);

        TrustManager[] trustManagers = tmf.getTrustManagers();
        final X509TrustManager origTrustManager = (X509TrustManager) trustManagers[0];

        TrustManager[] wrappedTrustManagers = new TrustManager[]{
                new X509TrustManager() {
                    @Override
                    public X509Certificate[] getAcceptedIssuers() {
                        return origTrustManager.getAcceptedIssuers();
                    }

                    @Override
                    public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
                        origTrustManager.checkClientTrusted(certs, authType);
                    }

                    @Override
                    public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
                        try {
                            origTrustManager.checkServerTrusted(certs, authType);
                        } catch (CertificateExpiredException ignored) {
                        }
                    }
                }
        };

        //SSLContext sc = SSLContext.getDefault();
        SSLContext sc = SSLContext.getInstance("TLS");
        sc.init(null, wrappedTrustManagers, null);
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    }
}

然后只需添加-javaagent:IgnoreExpiredServerCertificateAgent.jar到程序的 java 启动参数。

另请参阅SSL 和 TLS 之间的区别及其在 JavaJava 8 中的用法 SSLContext.getInstance("TLSv1.2") 是什么意思?SSLContext.getInstance()在你的情况下为适当的论据。


另请注意,具有过期证书的服务器也可能自己检查匹配的客户端证书的过期:

引起:javax.net.ssl.SSLHandshakeException:收到致命警报:com.sun.net.ssl.internal 的 com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174) 的证书过期。 ssl.Alerts.getSSLException(Alerts.java:136) 在 com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1822) 在 com.sun.net.ssl.internal.ssl.SSLSocketImpl。 readRecord(SSLSocketImpl.java:1004) 在 com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1188) 在 com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl. java:1215) 在 com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1199) 在 sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434) 在 sun .net.www.protocol.https.AbstractDelegateHttpsURLConnection。connect(AbstractDelegateHttpsURLConnection.java:166) 在 sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1195) 在 java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:379) 在 sun.net.www .protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:318)

如果您遇到这样的堆栈跟踪,那么在不接触服务器的情况下就无法缓解问题。正确的解决方案是重新签发具有未来到期日的证书。

于 2019-03-25T09:18:39.787 回答