首页 文章

如何在Java中以编程方式检查SSL证书过期日期

提问于
浏览
25

我需要从Java网站上的SSL证书中提取到期日期,应该同时支持可信和自签名证书,例如:1.trusted https://github.com 2.self-signed https://mms.nw.ru/

我已经将一些代码复制为:

import java.net.URL;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class SSLTest {

    public static void main(String [] args) throws Exception {
        // configure the SSLContext with a TrustManager
        SSLContext ctx = SSLContext.getInstance("TLS");
        ctx.init(new KeyManager[0], new TrustManager[] {new DefaultTrustManager()}, new SecureRandom());
        SSLContext.setDefault(ctx);

        URL url = new URL("https://github.com");//https://mms.nw.ru
        HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
        conn.setHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String arg0, SSLSession arg1) {
                return true;
            }
        });
        System.out.println(conn.getResponseCode());
        Certificate[] certs = conn.getServerCertificates();
        for (Certificate cert :certs){
            System.out.println(cert.getType());
            System.out.println(cert);
        }

        conn.disconnect();
    }

    private static class DefaultTrustManager implements X509TrustManager {

        @Override
        public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}

        @Override
        public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    }
}

问题是:

  • 如何解析证书的过期日期,在我的代码中,toString()确实输出了日期,但很难解析 .

  • 如何确定证书链,例如带链3的github证书,我如何知道从哪个证书中获取到期日期?

3 回答

  • 22

    如何从证书中解析到期日期

    将其转换为 X509Certificate 并调用 getNotAfter() .

    如何确定证书链,例如带链的github证书

    Certificate[]Certificate[] 数组是什么,正如它在Javadoc中所说的那样 .

    我如何知道从哪个证书中获取到期日期?

    阅读Javadoc . "The peer's own certificate first followed by any certificate authorities" .

    但是我不知道你为什么这么做 . Java应该已经为您完成了所有工作 .

    请丢掉那些不安全和不正确的TrustManager实现 . 处理自签名证书的正确方法是将它们导入客户端信任库 . 还请丢弃您不安全的HostnameVerifier,并使用默认的或安全的 . 如果您不希望它安全,为什么要使用HTTPS呢?

  • 0

    在Kotlin方式,它应该看起来像这样:

    fun certInformation(aURL: String) {
        val destinationURL = URL(aURL)
        val conn = destinationURL.openConnection() as HttpsURLConnection
        conn.connect()
        val certs = conn.serverCertificates
        for (cert in certs) {
            println("Certificate is: $cert")
            if (cert is X509Certificate) {
                println(cert.issuerDN.name)
                println(cert.notAfter)
                println(cert.notBefore)
            }
        }
    }
    
  • -1

    确保将开始/结束行附加到PEM格式,否则java不理解它 .

    public class CertTest {
    
        public static final String cert = "-----BEGIN CERTIFICATE-----\n<CERT_DATA>\n-----END CERTIFICATE-----";
    
        public static void main(String[] args){
            try {
                X509Certificate myCert = (X509Certificate)CertificateFactory
                         .getInstance("X509")
                         .generateCertificate(
                                           // string encoded with default charset
                        new ByteArrayInputStream(cert.getBytes())
                         );
                System.out.println(myCert.getNotAfter());
    
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
        }
    }
    

相关问题