javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: 没有与 IP 地址匹配的主题备用名称

javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names matching IP address

我有一个 java 应用程序调用外部 api 托管在 https://10.20.30.40:1234/test/myurl

这样的地址

这有一个带有 CN 的域基础证书,如 *.myappdomain.au

我们已经在我们的 linux 证书服务器上完成了注册。 我什至尝试使用以下代码加载证书,但它没有用,我们得到同样的错误

private static SSLSocketFactory createSSLSocketFactory(String certificatePath) throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
        File crtFile = new File(certificatePath);
        
        Certificate certificate = CertificateFactory.getInstance("X.509").generateCertificate(new FileInputStream(crtFile));

        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(null, null);
        keyStore.setCertificateEntry("server", certificate);

        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(keyStore);

        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, trustManagerFactory.getTrustManagers(), null);

        return sslContext.getSocketFactory();
    }

我试过的一件事是在主机中添加条目,比如 10.20.30.40 myappdomain.au 然后使用 url 之类的 https://myappdomain.au:1234/test/myurl

然后应用程序工作

知道我还需要做什么吗

嗯,如果 API 托管在一个 IP 地址上,SSL 证书必须将该 IP 地址定义为 Subject Alternative Name. This however won't work for services like Let's Encrypt

我想问题的主要原因是您试图通过 IP 地址而不是 FQDN 访问 API。将 API 的 URL 更改为源代码中 IP 地址的适当 DNS 名称应该会产生所有工作,只要 DNS 名称解析为与通配符证书所在域相关的内容颁发给(例如 api.myappdomain.au)。

在连接之前尝试运行此代码:

public static void trustAllCerts() {
    TrustManager[] trustAllCerts = new TrustManager[]{
            new X509TrustManager() {
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
                public void checkClientTrusted(
                    java.security.cert.X509Certificate[] certs, String authType) {
                }
                public void checkServerTrusted(
                    java.security.cert.X509Certificate[] certs, String authType) {
                }
            }
        };
    
    try {
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    } catch (Exception e) {
            
        e.printStackTrace();

    }
}