如何修复“java.security.cert.CertificateException:没有主题备选名称存在”错误? [英] How to fix the "java.security.cert.CertificateException: No subject alternative names present" error?
问题描述
我有一个Java Web服务客户端,它通过HTTPS消耗一个Web服务。
I have a Java web service client, which consumes a web service via HTTPS.
import javax.xml.ws.Service;
@WebServiceClient(name = "ISomeService", targetNamespace = "http://tempuri.org/", wsdlLocation = "...")
public class ISomeService
extends Service
{
public ISomeService() {
super(__getWsdlLocation(), ISOMESERVICE_QNAME);
}
当我连接到服务URL( https: //AAA.BBB.CCC.DDD:9443/ISomeService
),我得到异常 java.security.cert.CertificateException:没有主题备用名称存在
。
要修复它,我先运行 openssl s_client -showcerts -connect AAA.BBB.CCC.DDD:9443> certs.txt
,并在文件 certs.txt
中获得以下内容:
To fix it, I first ran openssl s_client -showcerts -connect AAA.BBB.CCC.DDD:9443 > certs.txt
and got following content in file certs.txt
:
CONNECTED(00000003)
---
Certificate chain
0 s:/CN=someSubdomain.someorganisation.com
i:/CN=someSubdomain.someorganisation.com
-----BEGIN CERTIFICATE-----
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-----END CERTIFICATE-----
---
Server certificate
subject=/CN=someSubdomain.someorganisation.com
issuer=/CN=someSubdomain.someorganisation.com
---
No client certificate CA names sent
---
SSL handshake has read 489 bytes and written 236 bytes
---
New, TLSv1/SSLv3, Cipher is RC4-MD5
Server public key is 512 bit
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : RC4-MD5
Session-ID: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Session-ID-ctx:
Master-Key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Key-Arg : None
Start Time: 1382521838
Timeout : 300 (sec)
Verify return code: 21 (unable to verify the first certificate)
---
AFAIK,现在我需要
AFAIK, now I need to
- 在
之间提取
certs.txt
的部分----- BEGIN CERTIFICATE -----和
----- END CERTIFICATE -----
, - 修改它,等于
AAA.BBB.CCC.DDD
和 - 然后使用
keytool -importcert导入结果 - 文件fileWithModifiedCertificate
(其中fileWithModifiedCertificate
为操作1和2的结果)。
- extract the part of
certs.txt
between-----BEGIN CERTIFICATE-----
and-----END CERTIFICATE-----
, - modify it so that the certificate name is equal to
AAA.BBB.CCC.DDD
and - then import the result using
keytool -importcert -file fileWithModifiedCertificate
(wherefileWithModifiedCertificate
is the result of operations 1 and 2).
这是否正确?
如果是这样,我如何使来自步骤1的证书与基于IP的adddress $ c> AAA.BBB.CCC.DDD )?
If so, how exactly can I make the certificate from step 1 work with IP-based adddress (AAA.BBB.CCC.DDD
) ?
更新1(23.10.2013 15:37 MSK) / STRONG>在回答一个的类似问题,我阅读以下内容:
如果您不能控制该服务器,请使用其主机名称(提供
,至少有一个CN与现有的
证书中的主机名相匹配)。
If you're not in control of that server, use its host name (provided that there is at least a CN matching that host name in the existing cert).
推荐答案
我通过使用提供的方法禁用HTTPS检查来解决问题在这里:
I fixed the problem by disabling HTTPS checks using the approach presented here:
我将以下代码放入 ISomeService
类中:
I put following code into the the ISomeService
class:
static {
disableSslVerification();
}
private static void disableSslVerification() {
try
{
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};
// Install the all-trusting trust manager
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
}
由于我使用 https://AAA.BBB.CCC.DDD:9443 / ISomeService
仅用于测试,这是一个很好的解决方案。
Since I'm using the https://AAA.BBB.CCC.DDD:9443/ISomeService
for testing purposes only, it's a good enough solution.
这篇关于如何修复“java.security.cert.CertificateException:没有主题备选名称存在”错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!