DP_*_*DP_ 98 java ssl https certificate ssl-certificate
我有一个Java Web服务客户端,它通过HTTPS使用Web服务.
import javax.xml.ws.Service;
@WebServiceClient(name = "ISomeService", targetNamespace = "http://tempuri.org/", wsdlLocation = "...")
public class ISomeService
extends Service
{
public ISomeService() {
super(__getWsdlLocation(), ISOMESERVICE_QNAME);
}
Run Code Online (Sandbox Code Playgroud)
当我连接到服务URL(https://AAA.BBB.CCC.DDD:9443/ISomeService)时,我得到了异常java.security.cert.CertificateException: No subject alternative names present.
为了解决这个问题,我首先运行openssl s_client -showcerts -connect AAA.BBB.CCC.DDD:9443 > certs.txt并在文件中获得以下内容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)
---
Run Code Online (Sandbox Code Playgroud)
AFAIK,现在我需要
certs.txt之间-----BEGIN CERTIFICATE-----和-----END CERTIFICATE-----,AAA.BBB.CCC.DDD和keytool -importcert -file fileWithModifiedCertificate(其中fileWithModifiedCertificate是操作1和2的结果)导入结果.它是否正确?
如果是这样,我如何才能使步骤1中的证书与基于IP的adddress(AAA.BBB.CCC.DDD)一起使用?
更新1( 2013年10月23日15:37 MSK):在回答类似问题时,我读了以下内容:
如果您无法控制该服务器,请使用其主机名(前提是在现有证书中至少存在与该主机名匹配的CN).
"使用"究竟是什么意思?
DP_*_*DP_ 146
我通过使用此处介绍的方法禁用HTTPS检查来解决问题:
我将以下代码放入ISomeService该类:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
由于我https://AAA.BBB.CCC.DDD:9443/ISomeService仅用于测试目的,因此它是一个足够好的解决方案.
jua*_*lgo 30
我有同样的问题,并用这段代码解决了.我在第一次调用webservices之前放了这段代码.
javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(
new javax.net.ssl.HostnameVerifier(){
public boolean verify(String hostname,
javax.net.ssl.SSLSession sslSession) {
return hostname.equals("localhost");
}
});
Run Code Online (Sandbox Code Playgroud)
它很简单,工作正常.
这是原始来源.
Bru*_*uno 22
根据客户端请求执行证书身份验证.
当您的客户端使用https://xxx.xxx.xxx.xxx/something(在哪里xxx.xxx.xxx.xxx是IP地址)时,将根据此IP地址检查证书身份(理论上,仅使用IP SAN扩展).
如果您的证书没有IP SAN,但没有DNS SAN(或者如果没有DNS SAN,主题DN中的公共名称),您可以通过使客户端使用具有该主机名的URL(或主机名)来使其工作.证书有效,如果有多个可能的值).例如,如果您的证书有名称www.example.com,请使用https://www.example.com/something.
当然,您需要该主机名才能解析为该IP地址.
此外,如果存在任何DNS SAN,则将忽略主题DN中的CN,因此在这种情况下使用与其中一个DNS SAN匹配的名称.
小智 21
这是一个老问题,但从JDK 1.8.0_144转到jdk 1.8.0_191时遇到了同样的问题
我们在更改日志中找到了一个提示:
我们添加了以下附加系统属性,这有助于我们解决此问题:
-Dcom.sun.jndi.ldap.object.disableEndpointIdentification=true
Run Code Online (Sandbox Code Playgroud)
小智 13
要导入证书:
openssl s_client -showcerts -connect AAA.BBB.CCC.DDD:9443 > certs.txt提取证书,例如,这将以PEM格式提取证书.openssl x509 -in certs.txt -out certs.der -outform DERsudo keytool -importcert -file certs.der -keystore <path-to-cacerts>默认cacerts密码为'changeit'.如果为FQDN颁发了证书,并且您正在尝试通过Java代码中的IP地址进行连接,那么这应该在您的代码中修复,而不是弄乱证书本身.将您的代码更改为通过FQDN连接.如果您的开发计算机上无法解析FQDN,只需将其添加到您的hosts文件,或使用可以解析此FQDN的DNS服务器配置您的计算机.
您可能不想禁用所有 ssl 验证,因此您可以通过以下方式禁用主机名验证,这比替代方案要简单一些:
HttpsURLConnection.setDefaultHostnameVerifier(
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Run Code Online (Sandbox Code Playgroud)
[编辑]
正如 conapart3 所提到的SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER,现在已弃用,因此它可能会在以后的版本中被删除,因此您将来可能会被迫推出自己的解决方案,尽管我仍然会说我会避开任何关闭所有验证的解决方案。
我以正确的方式解决了此问题,方法是在证书中添加主题alt名称,而不是进行任何代码更改或禁用SSL(与其他答案不同)。如果您清楚地看到异常,则说明“缺少主题名称”,因此正确的方法是添加它们
请查看此链接以逐步了解。
上面的错误表示您的JKS文件缺少尝试访问该应用程序所需的域。您将需要使用Open SSL和密钥工具来添加多个域
echo '[ subject_alt_name ]' >> openssl.cnfecho 'subjectAltName = DNS:example.mydomain1.com, DNS:example.mydomain2.com, DNS:example.mydomain3.com, DNS: localhost'>> openssl.cnfopenssl req -x509 -nodes -newkey rsa:2048 -config openssl.cnf -extensions subject_alt_name -keyout private.key -out self-signed.pem -subj '/C=gb/ST=edinburgh/L=edinburgh/O=mygroup/OU=servicing/CN=www.example.com/emailAddress=postmaster@example.com' -days 365将公钥(.pem)文件导出为PKS12格式。这将提示您输入密码
openssl pkcs12 -export -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -export -in
self-signed.pem -inkey private.key -name myalias -out keystore.p12
Run Code Online (Sandbox Code Playgroud)从自签名PEM(密钥库)创建a.JKS
keytool -importkeystore -destkeystore keystore.jks -deststoretype PKCS12 -srcstoretype PKCS12 -srckeystore keystore.p12
Run Code Online (Sandbox Code Playgroud)从上面的密钥库或JKS文件生成证书
keytool -export -keystore keystore.jks -alias myalias -file selfsigned.crt
Run Code Online (Sandbox Code Playgroud)由于上述证书是经过自签名的,并且未经CA验证,因此需要将其添加到Truststore中(对于Windows,对于MAC,在以下位置的CAcerts文件中,请找到您的JDK的安装位置。)
sudo keytool -importcert -file selfsigned.crt -alias myalias -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/security/cacerts
Run Code Online (Sandbox Code Playgroud)原始答案发布在此链接上。
| 归档时间: |
|
| 查看次数: |
347252 次 |
| 最近记录: |