如何忽略来自 Java 应用程序外部的过期证书?

How to ignore expired certificates from outside a Java application?(如何忽略来自 Java 应用程序外部的过期证书?)

本文介绍了如何忽略来自 Java 应用程序外部的过期证书?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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 environment variable that we could provide at start up that would allow us to have all expired cert's ignored for now, or even be more specific and provide externally the specific cert that we would like to have the expiration ignored.

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

Anyone have any ideas that would work?

推荐答案

这里是结合java - 忽略过期的 ssl 证书 和 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 启动参数中.

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

另请参阅 SSL 和 TLS 之间的区别及其Java 中的用法 和 Java 8 SSLContext.getInstance(TLSv1.2")这是什么意思?在您的情况下为 SSLContext.getInstance() 提供适当的参数.

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:

引起:javax.net.ssl.SSLHandshakeException:收到致命警报:证书过期时间com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)在com.sun.net.ssl.internal.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)

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.

这篇关于如何忽略来自 Java 应用程序外部的过期证书?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:如何忽略来自 Java 应用程序外部的过期证书?

基础教程推荐