SSL证书验证:javax.net.ssl.SSLHandshakeException [英] SSL Certificate Verification : javax.net.ssl.SSLHandshakeException
问题描述
我试图通过 Jersey客户端
调用HTTPS REST API。在开发过程中,我偶然发现以下错误:
I am trying to call a HTTPS REST API through Jersey Client
. And on the course of development i stumble upon following error :
Exception in thread "main" com.sun.jersey.api.client.ClientHandlerException: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching mvn.signify.abc.com found
at com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:149)
at com.sun.jersey.api.client.Client.handle(Client.java:648)
at com.sun.jersey.api.client.WebResource.handle(WebResource.java:670)
at com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74)
at com.sun.jersey.api.client.WebResource$Builder.get(WebResource.java:503)
at com.lftechnology.sbworkbench.utility.utils.PingFederateUtility.main(PingFederateUtility.java:32)
Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching mvn.signify.abc.com found
所以我把它搞砸了一下,找到了大量的解决方案,实际上有效。
So I goggled it out for a bit and found tons of solution for it , which actually works.
- 使用Jersey客户端的HTTPS
- https://gist.github.com/outbounder/1069465
- 如何修复java.security.cert.CertificateException:没有主题替代名称存在错误?
- http://www.mkyong.com/webservices/jax-ws/java-security-cert-certificateexception-no-name-matching-localhost-found/
- http://java.globinch.com/enterprise-java/security/fix-java-security-certificate-exception-no-matching-localhost-found/
- HTTPS using Jersey Client
- https://gist.github.com/outbounder/1069465
- How to fix the "java.security.cert.CertificateException: No subject alternative names present" error?
- http://www.mkyong.com/webservices/jax-ws/java-security-cert-certificateexception-no-name-matching-localhost-found/
- http://java.globinch.com/enterprise-java/security/fix-java-security-certificate-exception-no-matching-localhost-found/
他们在不同的领域,但他们有一个共同的解决方案来解决它。
They are in different domain but they have a common solution to work it out.
我目前在开发环境中使用自创的自签名证书。因此它必然会出现问题。
I am currently using a self created self-signed certificate in development environment. And hence it is bound to show up the issue.
上述解决方案侧重于跳过/允许验证所有证书。
The above mentioned solution focus on skipping / allowing all certificates to be verified.
但当我将其移至生产环境时,我可以从可信赖的来源访问有效签名证书。
But when i move it to the production environment , then i have access to Valid Signed Certificate from trustworthy source.
- 当我转向生产时,这些解决方案是否有任何帮助?
- 跳过SSL验证是否可以?
- 为
开发和生产环境实现通用解决方案的另一种替代方法是什么?
PS
我使用的解决方案是,
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();
}
然后我与泽西合作
让它工作。它工作得很好。
which i then in-cooperate with Jersey
to make it work. And it is working great.
所以,再次问题
。 此解决方案是否适用于生产环境?
推荐答案
我目前在
开发环境中使用自创的自签名证书。 ... javax.net.ssl.SSLHandshakeException:
java.security.cert.CertificateException:找不到与
dev.ppc.lftechnology.com匹配的名称
I am currently using a self created self-signed certificate in development environment. ... javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching dev.ppc.lftechnology.com found
看来自签名证书不正确。
It appears the self signed certificate is incorrect.
以下是OpenSSL CONF
file我用来创建自签名证书和证书请求,以便在测试期间使用。将其另存为 example-com.conf
。更改 [alternate_names]
下的DNS名称以满足您的口味。你甚至可以把 localhost
, localhost.localdomain
和 127.0.0.1
在那里进行测试。
Below is the OpenSSL CONF
file I use to create self signed certificates and certificate requests to use during testing. Save it as example-com.conf
. Change the DNS names under [ alternate_names ]
to suit your tastes. You can even put localhost
, localhost.localdomain
and 127.0.0.1
in there for testing.
如果要创建自签名证书,请使用:
If you want to create a self signed certificate, then use:
openssl req -config example-com.conf -new -x509 -newkey rsa:2048 \
-nodes -keyout example-com.key.pem -days 365 -out example-com.cert.pem
如果要创建将签名的签名请求(CSR)由受信任的机构,然后使用:
If you want to create a signing request (CSR) that will be signed by a trusted authority, then use:
openssl req -config example-com.conf -new -newkey rsa:2048 \
-nodes -keyout example-com.key.pem -days 365 -out example-com.req.pem
自签名证书和签名请求之间的区别是 -x509
选项。当 -x509
存在时,将创建一个自签名证书。缺少 -x509
表示已创建请求。
The difference between a self signed certificate and a signing request is the -x509
option. With -x509
present, a self signed certificate is created. The absence of -x509
means a request is created.
如果要打印自签名证书或请求要查看其实际内容,请使用:
If you want to print your self signed certificate or request to see what's actually in it, then use:
openssl x509 -in example-com.cert.pem -text -noout
openssl req -in example-com.req.pem -text -noout
如果你想要测试服务器,然后使用 s_client
:
If you want to test the server, then use s_client
:
openssl s_client -connect <server>:<port> -CAfile <trust-anchor.pem>
上述命令应该以类似的消息结束验证OK(0)
。如果您没有收到验证确定(0)
,请修复您的测试装备。一旦OpenSSL成功完成,那就成了你的基线。
The above command should finish with a message similar to Verify OK (0)
. If you don't receive Verify OK (0)
, then fix your test rig. Once OpenSSL completes successfully, then that becomes your baseline.
[ req ]
default_bits = 2048
default_keyfile = server-key.pem
distinguished_name = subject
req_extensions = req_extensions
x509_extensions = cert_extensions
string_mask = utf8only
[ subject ]
countryName = Country Name (2 letter code)
countryName_default = US
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = NY
localityName = Locality Name (eg, city)
localityName_default = New York
organizationName = Organization Name (eg, company)
organizationName_default = Example, LLC
# Use a friendly name here. Its presented to the user.
# The server's DNS name show up in Subject Alternate Names. Plus,
# DNS names here is deprecated by both IETF and CA/Browser Forums.
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_default = Example Company
emailAddress = Email Address
emailAddress_default = test@example.com
[ cert_extensions ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
# extendedKeyUsage = serverAuth
subjectAltName = @alternate_names
nsComment = "OpenSSL Generated Certificate"
[ req_extensions ]
subjectKeyIdentifier = hash
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
# extendedKeyUsage = serverAuth
subjectAltName = @alternate_names
nsComment = "OpenSSL Generated Certificate"
[ alternate_names ]
DNS.1 = example.com
DNS.2 = www.example.com
DNS.3 = mail.example.com
DNS.4 = ftp.example.com
# Add these if you need them. But usually you don't want them or
# need them in production. You may need them for development.
# DNS.5 = localhost
# DNS.6 = localhost.localdomain
# DNS.7 = 127.0.0.1
跳过SSL验证是否可以?
Is it OK to skip SSL verification ?
没有。这是非常不负责任的。如果你不打算正确使用PKIX,那么为什么要使用它呢?
No. That's very irresponsible. If you are not going to use PKIX correctly, then why use it at all?
这是我想到的:世界上最危险的代码:在非浏览器软件中验证SSL证书。
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
最好在密钥库中加载自签名证书(或加载私有CA),然后将其传递给 SSLContext.init
。然后一切都按预期工作,并且不需要信任所有内容或从验证
返回 true
。
Its better to load your self signed certificate in a Keystore (or load your private CA), and then pass it to SSLContext.init
. Then everything works as intended, and there's no need to trust everything or return true
from verify
.
Bruno和EJP有很多答案涵盖该主题。
Bruno and EJP have plenty of answers covering that subject.
为开发和生产环境实现通用解决方案的另一种替代方法是什么?
What are the other alternate way to achieve a common solution for both development and production environment?
使用格式良好的证书链回到受信任的根。
Use a well formed certificate that chains back to a trusted root.
为了进行测试,您可以创建自签名证书。或者,创建证书请求并由内部CA在私有PKI中签名。在这种情况下,您需要信任自签名证书或信任您的内部CA.
For testing, you can create a self signed certificate. Or, create a certificate request and have it signed by your internal CA in a private PKI. In this case, you need to trust your self signed certificate or trust your internal CA.
对于生产,您可以使用由CA的其中一个成员签名的证书动物园,所以组织外的其他人也信任它。 StartCom 和 CACert 提供免费的Class 1证书。
For production, you can use a certificate signed by one of the members of the CA Zoo so others outside the organization trusts it too. StartCom and CACert offer free Class 1 certificates.
第1类证书通常经过域验证,不允许使用通配符。虽然Class 1是免费发行的,但他们会收取撤销费用,因为这是成本所在。
Class 1 certificates are usually domain validated and don't allow wild cards. While the Class 1 is issued for free, they charge for revocation because that's where the cost lies.
如果您需要外卡,那么您通常会购买一个类2或更高。
If you need a wild card, then you will usually to purchase a Class 2 or higher.
这篇关于SSL证书验证:javax.net.ssl.SSLHandshakeException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!