我们有一个Java应用程序,我们需要忽略过期的自签名证书,但是我们无法修改代码来执行此操作。我想知道是否有一个我们可以在启动时提供的系统属性或环境变量,这将允许我们暂时忽略所有过期的证书,或者甚至更具体,并在外部提供我们希望过期的特定证书忽略。
任何人都有任何可行的想法吗?
答案 0 :(得分:1)
另一种方法是使用keytool
将过期的证书作为可信证书导入客户端密钥库。你试过了吗?
更好的替代方法是使用非自签名的当前证书替换服务器中的过期证书。
答案 1 :(得分:-1)
这是结合java - ignore expired ssl certificate和Java SSL: how to disable hostname verification获得的解决方案。
public class IgnoreExpiredServerCertificateAgent {
public static void premain(String args, Instrumentation inst) throws Exception {
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init((KeyStore) null);
TrustManager[] trustManagers = tmf.getTrustManagers();
final X509TrustManager origTrustManager = (X509TrustManager) trustManagers[0];
TrustManager[] wrappedTrustManagers = new TrustManager[]{
new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
return origTrustManager.getAcceptedIssuers();
}
@Override
public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
origTrustManager.checkClientTrusted(certs, authType);
}
@Override
public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
try {
origTrustManager.checkServerTrusted(certs, authType);
} catch (CertificateExpiredException ignored) {
}
}
}
};
//SSLContext sc = SSLContext.getDefault();
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, wrappedTrustManagers, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
}
}
然后只需在程序的Java启动参数中添加-javaagent:IgnoreExpiredServerCertificateAgent.jar
。
请参见Difference between SSL and TLS and their usage in Java和Java 8 SSLContext.getInstance("TLSv1.2") what does it mean?,以了解适用于您的情况的SSLContext.getInstance()
的参数。
还请注意,具有过期证书的服务器本身也可能会检查匹配的客户端证书的有效期:
由以下原因引起:javax.net.ssl.SSLHandshakeException:收到致命警报: certificate_expired at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174) 在 com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136) 在 com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1822) 在 com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1004) 在 com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1188) 在 com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1215) 在 com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1199) 在 sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434) 在 sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166) 在 sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1195) 在 java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:379) 在 sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:318)
如果遇到这样的堆栈跟踪,那么不接触服务器就无法缓解问题。 正确的解决方案是在将来的到期日重新发行证书。