我正在尝试通过 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
我花了一点时间在Google上搜索,发现有很多解决方法都可以解决这个问题。
- 使用Jersey Client进行HTTPS
- https://gist.github.com/outbounder/1069465
- 如何解决"java.security.cert.CertificateException: No subject alternative names present"错误?
- 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/
它们来自不同的领域,但都有一个通用的解决方案。
场景
我目前在开发环境中使用自己创建的自签名证书。因此,这个问题必然会出现。
问题
上述解决方案重点在于跳过/允许验证所有证书。
但是当我将其移动到生产环境时,我可以从可信源获得有效签名证书。
- 那么这些解决方案对我在生产中的使用有帮助吗?
- 跳过SSL验证是否可以接受?
- 还有其他替代方法可以为开发和生产环境实现共同的解决方案吗?
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
使其正常工作。目前工作得非常好。
所以,问题又来了。这个解决方案是否适用于生产环境?不过,如果您不想修改返回的实体,则最好以只读模式获取实体。这将允许Hibernate放弃关联的分离状态,该状态用于检测实体状态修改的脏检查机制。此外,只读实体在刷新期间被忽略。