我试图通过Jersey Client
调用HTTPS REST API。在开发过程中,我偶然发现了以下错误:
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
所以我搜索了一下,发现了大量的解决方案,实际上有效。
他们处于不同的领域,但他们有一个共同的解决方案来解决它。
我目前在开发环境中使用自创的自签名证书。因此它必然会出现问题。
上述解决方案侧重于跳过/允许验证所有证书。
但是当我将其移至生产环境时,我可以从可信赖的来源访问有效签名证书。
P.S
我使用的解决方案是,
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();
}
然后我与Jersey
合作以使其有效。它工作得很好。
所以,再次Question
。 此解决方案是否适用于生产环境?
但是,您不希望修改返回的实体,以只读模式获取实体要好得多。这将允许Hibernate丢弃相关的分离状态,脏状态检查机制使用该分离状态来检测实体状态修改。更多,在刷新期间会跳过只读实体。
答案 0 :(得分:13)
我目前正在使用自创的自签名证书 发展环境。 ... javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException:没有名称匹配 dev.ppc.lftechnology.com发现
自签名证书似乎不正确。
下面是我用来创建自签名证书和证书请求的OpenSSL CONF
文件,以便在测试期间使用。将其另存为example-com.conf
。更改[ alternate_names ]
下的DNS名称以符合您的口味。您甚至可以将localhost
,localhost.localdomain
和127.0.0.1
放在那里进行测试。
如果要创建自签名证书,请使用:
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),请使用:
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
表示已创建请求。
如果您要打印自签名证书或要求查看其中的实际内容,请使用:
openssl x509 -in example-com.cert.pem -text -noout
openssl req -in example-com.req.pem -text -noout
如果要测试服务器,请使用s_client
:
openssl s_client -connect <server>:<port> -CAfile <trust-anchor.pem>
上述命令应该以类似于Verify OK (0)
的消息结束。如果您没有收到Verify OK (0)
,请修复您的测试平台。一旦OpenSSL成功完成,那么这将成为您的基线。
[ 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验证是否可以?
没有。这是非常不负责任的。如果您不打算正确使用PKIX,那么为什么要使用它?
我想到了这一点:The Most Dangerous Code in the World: Validating SSL Certificates in Non-Browser Software。
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
最好在密钥库中加载自签名证书(或加载私有CA),然后将其传递给SSLContext.init
。然后一切都按预期工作,并且不需要信任所有内容或从true
返回verify
。
布鲁诺和EJP有很多关于这个主题的答案。
为开发和生产环境实现通用解决方案的另一种替代方法是什么?
使用格式良好的证书链接回受信任的根目录。
要进行测试,您可以创建自签名证书。或者,创建证书请求并由内部CA在私有PKI中签名。在这种情况下,您需要信任自签名证书或信任您的内部CA.
对于生产,您可以使用由CA Zoo的其中一个成员签名的证书,以便组织外的其他人也信任它。 StartCom和CACert提供免费的1级证书。
第1类证书通常经过域验证,不允许使用通配符。虽然Class 1是免费发行的,但他们会收取撤销费用,因为这是成本所在。
如果您需要外卡,那么您通常会购买2级或更高级别。
答案 1 :(得分:6)
@jww正确回答了问题
跳过SSL验证是否可以?不,这是非常不负责任的。
但是,在某些情况下,您可能无法控制相关服务器以便能够安装有效的证书。如果服务器属于其他人,并且您信任该服务器,则更好的解决方案是使用“白名单”仅验证受信任服务器的证书,否则使用正常验证。
public static class WhitelistHostnameVerifier implements HostnameVerifier {
private static final HostnameVerifier defaultHostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
private Set<String> trustedHosts;
public WhitelistHostnameVerifier(Set<String> trustedHosts) {
this.trustedHosts = trustedHosts;
}
@Override
public boolean verify(String hostname, SSLSession session) {
if (trustedHosts.contains(hostname)) {
return true;
} else {
return defaultHostnameVerifier.verify(hostname, session);
}
}
}
安装一次:
HttpsURLConnection.setDefaultHostnameVerifier(
new WhitelistHostnameVerifier(Sets.newHashSet("trustedhost.mydomain.com")));
如果您要禁用安全检查,请不要全局执行...
答案 2 :(得分:1)
创建自签名证书时,Java Keytool for Java版本1.7.0_60-b19存在标签软件错误。请参阅这些说明以供参考。
https://www.sslshopper.com/article-how-to-create-a-self-signed-certificate-using-java-keytool.html
当它提示您输入&#34;您的名字和姓氏是什么?&#34;而不是输入您的姓名时,您应输入公用名,或(服务器的完全限定域名)。< / p>
[root@localhost ~]# keytool -genkey -keyalg RSA -alias myalias -keystore keystore.jks -storepass XXXXXX -validity 360 -keysize 2048
What is your first and last name?
[Unknown]: Angus MacGyver
What is the name of your organizational unit?
[Unknown]: My Department
What is the name of your organization?
[Unknown]: My Company
What is the name of your City or Locality?
[Unknown]: My City
What is the name of your State or Province?
[Unknown]: My State
What is the two-letter country code for this unit?
[Unknown]: US
Is CN=Angus MacGyver, OU=My Department, O=My Company, L=My City, ST=My State, C=US correct?
[no]: yes
Enter key password for <selfsigned>
(RETURN if same as keystore password):XXXXXX
Re-enter new password:XXXXXX
您可以验证&#34; CN&#34;通过调用它来正确设置(通用名称)属性:
[root@localhost ~]# keytool -v -list -keystore keystore.jks
查找Java版本:
[root@localhost ~]# java -version
java version "1.7.0_60"
Java(TM) SE Runtime Environment (build 1.7.0_60-b19)
Java HotSpot(TM) Client VM (build 24.60-b09, mixed mode, sharing)