URL myUrl = new URL("https://www.....");
网站的SSL证书已过期。如何避免此问题并使URL()正常工作?
您应该构建一个TrustManager
,它包装了默认的信任管理器,捕获CertificiateExpiredException
并忽略它。
注意:正如这个答案所详细说明的那样,这是否安全非常依赖于实现。特别是,它依赖于日期验证在所有其他内容正确检查之后最后进行。
以下内容应该可以工作:
TrustManagerFactory tmf = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
// Initialise the TMF as you normally would, for example:
tmf.init((KeyStore)null);
TrustManager[] trustManagers = tmf.getTrustManagers();
final X509TrustManager origTrustmanager = (X509TrustManager)trustManagers[0];
TrustManager[] wrappedTrustManagers = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return origTrustmanager.getAcceptedIssuers();
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
origTrustmanager.checkClientTrusted(certs, authType);
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
try {
origTrustmanager.checkServerTrusted(certs, authType);
} catch (CertificateExpiredException e) {}
}
}
};
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, wrappedTrustManagers, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
CertificateException
(有关详细信息,请参见子类)。请明确要捕获/忽略的内容。您真正想要验证的所有内容都必须在可能抛出的内容之前进行检查,否则您将不得不手动验证它。任何比此更轻松的行为(特别是什么都不做,因此不会抛出任何异常)都将完全忽略证书验证和验证,这与使用匿名密码套件或忽略身份验证几乎相同。这将破坏使用SSL/TLS的安全目的(与仅在到期日期上更具灵活性不同)。你需要创建一个自定义的X509验证器,它将忽略过期的证书。实际上,不会执行任何检查。
代码取自这里:http://exampledepot.com/egs/javax.net.ssl/TrustAll.html
// 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(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
}
};
// Install the all-trusting trust manager
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
}
// Now you can access an https URL without having the certificate in the truststore
// It should work with expired certificate as well
try {
URL myUrl = new URL("https://www.....");
} catch (MalformedURLException e) {
}
TrustManager
一样:这将首先破坏使用SSL/TLS的目的。 - BrunocheckValidity
被调用了,但是我不得不设置方法断点而不是行号断点,因为这些方法的主体为空。我不确定固定证书是否会有所不同,但如果您使用自签名证书作为服务器证书(而不是叶子证书),那么可能会改变行为。如果TLS服务器的公共部分与信任存储中的自签名证书的公共密钥相同,则其余检查都无关紧要。(未测试发生了什么) - dncook