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

发布于 2024-08-31 08:18:56 字数 147 浏览 5 评论 0原文

我们有一个 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

┾廆蒐ゝ 2024-09-07 08:18:56

这是通过组合 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 启动参数中即可。

另请参阅 SSL 和 TLS 之间的差异及其在 Java 中的用法Java 8 SSLContext.getInstance("TLSv1. 2") 这意味着什么? 在您的情况下获取 SSLContext.getInstance() 的适当参数。


另请注意,证书过期的服务器也可能会自行检查匹配的客户端证书是否过期:

由以下原因引起: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)

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文