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();
}
}
我有一个 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();
}
}