How to ignore expired certificates from outside a Java application?

前端 未结 1 1968
梦毁少年i
梦毁少年i 2021-01-23 11:13

We have a Java application that we need to ignore an expired self-signed cert, however we cannot modify the code to do this. I wondering if there was a System Property or envir

相关标签:
1条回答
  • 2021-01-23 11:46

    Here is the solution obtained by combining java - ignore expired ssl certificate and Java SSL: how to disable hostname verification.

    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());
        }
    }
    

    Then just add -javaagent:IgnoreExpiredServerCertificateAgent.jar to program's java startup arguments.

    See also Difference between SSL and TLS and their usage in Java and Java 8 SSLContext.getInstance("TLSv1.2") what does it mean? for appropriate argument for SSLContext.getInstance() in your case.


    Also note that the server with expired certificate may also itself check the expiry of the matching client certificate:

    Caused by:javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_expired at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174) at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1822) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1004) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1188) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1215) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1199) at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434) at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166) at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1195) at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:379) at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:318)

    If you meet such stacktrace then there is no way to mitigate the problem without touching the server. And the proper solution would be to reissue the certificate with future expiry date.

    0 讨论(0)
提交回复
热议问题