【问题标题】:Enable SSL certificate revocation checking in OpenJDK 11在 OpenJDK 11 中启用 SSL 证书吊销检查
【发布时间】:2019-08-15 17:32:15
【问题描述】:

在 Java 11 中是否有一些快速的“声明性”方式,而不是繁琐的手动实现来检查证书是否被吊销?

我尝试使用此答案中的属性: Check X509 certificate revocation status in Spring-Security before authenticating 使用此虚拟吊销证书:https://revoked.badssl.com 但代码始终接受证书。我是在做错什么,还是这些属性对于 Java 11 不再实际?如果是这样,我们还有其他选择吗?

下面是我的代码:

public static void validateOnCertificateRevocation(boolean check) {
    if (check) {
        System.setProperty("com.sun.net.ssl.checkRevocation", "true");
        System.setProperty("com.sun.security.enableCRLDP", "true");

        Security.setProperty("ocsp.enable", "true");
    }

    try {
        new URL("https://revoked.badssl.com").openConnection().connect();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

【问题讨论】:

    标签: ssl ssl-certificate java-11 certificate-revocation


    【解决方案1】:

    似乎必须在执行第一个请求之前设置这些选项。

    因此,作为独立 Java 程序的以下代码会引发 CertPathValidatorException: Certificate has been revoked(在 Windows 上使用 OpenJDK 11.0.2 x64 测试):

    public static void main(String[] args) {
        validateOnCertificateRevocation(true); // throws CertPathValidatorException
    }
    

    但是以下代码不会导致任何错误/异常:

    public static void main(String[] args) {
        validateOnCertificateRevocation(false);
        validateOnCertificateRevocation(true); // nothing happens
    }
    

    您可以看到在处理第一个请求后更改选项无效。我假设这些选项是在一些证书验证相关类的static { ... } 块中处理的。

    如果您仍想基于每个请求启用/禁用证书吊销检查,您可以通过实现您自己的使用 CertPathValidatorX509TrustManager 来实现(您可以通过 @987654329 启用/禁用证书吊销检查@。

    或者,有一种解决方案可以全局启用证书吊销检查并显式处理 CertificateRevokedException:

    private boolean checkOnCertificateRevocation;
    
    @Override
    public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
        try {
            getDefaultTrustManager().checkServerTrusted(certs, authType);
        } catch (CertificateException e) {
            if (checkOnCertificateRevocation) {
                if (getRootCause(e) instanceof CertificateRevokedException) {
                    throw e;
                }
            }
        }
    }
    

    【讨论】:

    • 谢谢!正如您所料,“com.sun.net.ssl.checkRevocation”属性实际上只在初始化“sun.security.validator.PKIXValidator”类中的静态字段“checkTLSRevocation”时被处理一次。因此,作为一种解决方法,我们可以始终启用此属性并根据客户端代码中的布尔标志捕获/重新抛出异常。但是也许存在一些更优雅的解决方案来启用/禁用每个请求中的撤销检查?
    • 您可以实现自己的X509TrustManager,使用CertPathValidator 来验证证书。使用的PKIXParameters 类有一个名为setRevocationEnabled(boolen) 的方法,可以启用/禁用证书吊销检查。这应该适用于每个请求级别。
    • 感谢您的帮助!然而,在多次尝试实现过于复杂的CertPathValidator 之后,它决定坚持“总是扔,需要时抓住”的原则。自定义 X509TrustManager 的最终代码现在看起来像 @Override public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException { try { getDefaultTrustManager().checkServerTrusted(certs, authType); } catch (CertificateException e) { if (checkOnCertificateRevocation) { if (getRootCause(e) instanceof CertificateRevokedException) { throw e; } } } }
    • @Roman 我更新了我的答案,并包含了我们来自 cmets 的讨论。
    猜你喜欢
    • 2016-11-13
    • 1970-01-01
    • 1970-01-01
    • 2018-01-15
    • 2011-07-18
    • 1970-01-01
    • 2012-02-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多