编程语言
首页 > 编程语言> > java – 如何检索不受信任的SSL服务器证书以便查看和信任它?

java – 如何检索不受信任的SSL服务器证书以便查看和信任它?

作者:互联网

我的问题:

我想连接到服务器(不限于HTTPS协议 – 可能是LDAP-over-SSL,可能是SMTPS,可能是IMAPS等),可能正在使用Java默认不信任的证书(因为它们是自签名).

所需的工作流程是尝试连接,检索证书信息,将其呈现给用户,如果他接受,则将其添加到信任库,以便将其信任.

我被困在检索证书.我有代码(请参阅帖子的末尾),我已经从这里和从有关java SSL的问题的答案指向的站点中得到了解释.代码只是创建一个SSLSocket,启动SSL握手,并向SSL会话询问Certificate [].当我使用已经可信任的证书连接到服务器时,代码工作正常.但是当我使用自签名证书连接到服务器时,我会得到通常的:

Exception in thread "main" javax.net.ssl.SSLHandshakeException: 
   sun.security.validator.ValidatorException: PKIX path building failed:
   sun.security.provider.certpath.SunCertPathBuilderException: unable to 
   find valid certification path to requested target
        at sun.security.ssl.Alerts.getSSLException(Unknown Source)
        at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source)
        at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
        at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
        at sun.security.ssl.ClientHandshaker.serverCertificate(Unknown Source)
        [etc]

如果我使用-Djavax.net.debug = all运行,我会看到JVM确实检索了自签名证书,但是在它返回证书之前,它会破坏连接以使用不受信任的证书.

看起来像鸡蛋问题.它不会让我看到证书,因为它们不受信任.但我需要看到证书能够将它们添加到信任库,以便它们可信.你怎么突破这个?

例如,如果我将程序运行为:

java SSLTest www.google.com 443

我得到了Google正在使用的证书的打印输出.但如果我把它作为

java SSLTest my.imap.server 993

我得到上面引用的异常.

编码:

import java.io.InputStream;
import java.io.OutputStream;
import java.security.cert.*;
import javax.net.SocketFactory;
import javax.net.ssl.*;

public class SSLTest
{
    public static void main(String[] args) throws Exception {
        if (args.length != 2) {
            System.err.println("Usage: SSLTest host port");
            return;
        }

        String host = args[0];
        int port = Integer.parseInt(args[1]);

        SocketFactory factory = SSLSocketFactory.getDefault();
        SSLSocket socket = (SSLSocket) factory.createSocket(host, port);

        socket.startHandshake();

        Certificate[] certs = socket.getSession().getPeerCertificates();

        System.out.println("Certs retrieved: " + certs.length);
        for (Certificate cert : certs) {
            System.out.println("Certificate is: " + cert);
            if(cert instanceof X509Certificate) {
                try {
                    ( (X509Certificate) cert).checkValidity();
                    System.out.println("Certificate is active for current date");
                } catch(CertificateExpiredException cee) {
                    System.out.println("Certificate is expired");
                }
            }
        }
    }
}

解决方法:

见这copy of Andreas Sterbenz’s InstallCert utility.

标签:java,ssl,ssl-certificate
来源: https://codeday.me/bug/20191004/1853907.html