Java SSL/TLS忽略过期证书?(java.security.cert.CertPathValidatorException:时间戳检查失败)

20

我在使用一个通过SSL通信的API时遇到了问题。我认为出现异常的原因是SSL证书已过期。但问题是我不管理API服务器。是否有可能忽略过期的证书?

异常:

[ERROR,TaacWorkshop] Problem deleting user group from CADA: 
org.apache.thrift.transport.TTransportException: javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: timestamp check failed
    at org.apache.thrift.transport.TIOStreamTransport.flush(TIOStreamTransport.java:156)
    at company.oss.thrift.cada.CADABackend$Client.send_DeleteUserGroup(CADABackend.java:580)
    at company.oss.thrift.cada.CADABackend$Client.DeleteUserGroup(CADABackend.java:568)
    at com.cable.company.nse.cada.CadaDao.deleteUserGroup(CadaDao.java:72)
    at com.cable.company.nse.taac.business.TaacWorkshop.deleteTaac(TaacWorkshop.java:127)
    at com.cable.company.nse.taac.controller.RemoteVendorAccessController.processRequest(RemoteVendorAccessController.java:130)
    at com.cable.company.nse.taac.controller.RemoteVendorAccessController$$FastClassByCGLIB$$63639bdf.invoke(<generated>)
    at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
    at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:692)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
    at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:67)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:625)
    at com.cable.company.nse.taac.controller.RemoteVendorAccessController$$EnhancerByCGLIB$$bdd8aaad.processRequest(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:592)
    at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.doInvokeMethod(HandlerMethodInvoker.java:710)
    at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:167)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:414)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:402)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:771)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:716)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:647)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:563)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:343)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:100)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:78)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:35)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:188)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    at org.springframework.security.web.session.ConcurrentSessionFilter.doFilter(ConcurrentSessionFilter.java:109)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:149)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:613)
Caused by: javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: timestamp check failed
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.checkEOF(SSLSocketImpl.java:1232)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.checkWrite(SSLSocketImpl.java:1244)
    at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.java:43)
    at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
    at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
    at org.apache.thrift.transport.TIOStreamTransport.flush(TIOStreamTransport.java:154)
    ... 66 more
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: timestamp check failed
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:150)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1584)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:174)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:168)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:848)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:106)
    at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:495)
    at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:433)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:877)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1089)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:618)
    at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.java:59)
    at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
    at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
    at org.apache.thrift.transport.TIOStreamTransport.flush(TIOStreamTransport.java:154)
    at company.oss.thrift.cada.CADABackend$Client.send_CreateUserGroup(CADABackend.java:546)
    at company.oss.thrift.cada.CADABackend$Client.CreateUserGroup(CADABackend.java:534)
    at com.cable.company.nse.cada.CadaDao.createUserGroup(CadaDao.java:93)
    at com.cable.company.nse.taac.business.TaacWorkshop.createTaac(TaacWorkshop.java:210)
    at com.cable.company.nse.taac.controller.RemoteVendorAccessController.processRequest(RemoteVendorAccessController.java:111)
    ... 61 more
Caused by: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: timestamp check failed
    at sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:187)
    at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:130)
    at sun.security.validator.Validator.validate(Validator.java:203)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:172)
    at com.sun.net.ssl.internal.ssl.JsseX509TrustManager.checkServerTrusted(SSLContextImpl.java:320)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:841)
    ... 76 more
Caused by: java.security.cert.CertPathValidatorException: timestamp check failed
    at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:139)
    at sun.security.provider.certpath.PKIXCertPathValidator.doValidate(PKIXCertPathValidator.java:316)
    at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:178)
    at java.security.cert.CertPathValidator.validate(CertPathValidator.java:206)
    at sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:182)
    ... 81 more
Caused by: java.security.cert.CertificateExpiredException: NotAfter: Sat Jul 17 13:44:42 MDT 2010
    at sun.security.x509.CertificateValidity.valid(CertificateValidity.java:256)
    at sun.security.x509.X509CertImpl.checkValidity(X509CertImpl.java:570)
    at sun.security.provider.certpath.BasicChecker.verifyTimestamp(BasicChecker.java:157)
    at sun.security.provider.certpath.BasicChecker.check(BasicChecker.java:109)
    at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:117)
    ... 85 more

目前的代码需要能够设置信任库,因为存在客户端证书认证。我已经尝试了以下建议,但仍然遇到一些问题。这是我目前使用的代码:

        KeyStore identityStore = KeyStore.getInstance(KeyStore.getDefaultType());
        ClassPathResource keystore = new ClassPathResource(cadaBackendCertFile);

        identityStore.load(keystore.getInputStream(), cadaBackendCertFilePassword.toCharArray());

        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(identityStore, cadaBackendCertFilePassword.toCharArray());

        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(identityStore);

        SSLContext ctx = SSLContext.getInstance("TLS");
        ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());

        SSLSocketFactory fac = ctx.getSocketFactory();
        Socket sslsock = fac.createSocket(cadaBackendEndpoint, cadaBackendPort);
        TTransport transport = new TSocket(sslsock);

将代码更改为以下内容,虽然会出现服务器问题,但它解决了我的安全异常问题:

        KeyStore identityStore = KeyStore.getInstance(KeyStore.getDefaultType());
        ClassPathResource keystore = new ClassPathResource(cadaBackendCertFile);

        identityStore.load(keystore.getInputStream(), cadaBackendCertFilePassword.toCharArray());

        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(identityStore, cadaBackendCertFilePassword.toCharArray());

        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(identityStore);

        SSLContext ctx = SSLContext.getInstance("TLS");
        ctx.init(kmf.getKeyManagers(), new TrustManager[] {new X509TrustManager(){
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }
            public void checkServerTrusted(X509Certificate[] chain,String authType) throws CertificateException {               
            }
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }       
        }}, new SecureRandom());

        SSLSocketFactory fac = ctx.getSocketFactory();
        Socket sslsock = fac.createSocket(cadaBackendEndpoint, cadaBackendPort);
        TTransport transport = new TSocket(sslsock);

        TProtocol proto = new TBinaryProtocol(transport);
        cadaBackendClient = new Client(proto);

实际上 - 即使是上面的代码也会抛出异常:

ERROR[com.cable.nse.cada.CadaDaoTest][main] - Error:
org.apache.thrift.transport.TTransportException: javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
    at org.apache.thrift.transport.TIOStreamTransport.flush(TIOStreamTransport.java:156)
    at .oss.thrift.cada.CADABackend$Client.send_UserDetails(CADABackend.java:328)
    at .oss.thrift.cada.CADABackend$Client.UserDetails(CADABackend.java:316)
    at com.cable.nse.cada.CadaDao.getUserDetails(CadaDao.java:136)
    at com.cable.nse.cada.CadaDaoTest.testCada(CadaDaoTest.java:73)
    at com.cable.nse.cada.CadaDaoTest.test(CadaDaoTest.java:37)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:592)
    at junit.framework.TestCase.runTest(TestCase.java:154)
    at junit.framework.TestCase.runBare(TestCase.java:127)
    at junit.framework.TestResult$1.protect(TestResult.java:106)
    at junit.framework.TestResult.runProtected(TestResult.java:124)
    at junit.framework.TestResult.run(TestResult.java:109)
    at junit.framework.TestCase.run(TestCase.java:118)
    at junit.framework.TestSuite.runTest(TestSuite.java:208)
    at junit.framework.TestSuite.run(TestSuite.java:203)
    at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:150)
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:117)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1650)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:925)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1089)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:618)
    at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.java:59)
    at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
    at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
    at org.apache.thrift.transport.TIOStreamTransport.flush(TIOStreamTransport.java:154)
    ... 23 more

在您的编辑版本中,您正在为keymanager和trustmanager使用相同的密钥库(这可能是有意的,不确定)。如果您没有使用客户端证书身份验证,则不需要它,请使用SSLContext.init(...)的第一个参数作为null。如果服务器可选请求客户端证书身份验证,并且客户端发送了服务器不接受的证书,则会出现此类错误。 - Bruno
我确实拥有客户端证书认证。密钥库包含客户端证书以及终端的自签名证书。因此,错误很可能是因为服务器不接受该证书? - wuntee
3个回答

10

更改默认的SSLContext不安全,因为它会影响整个进程。这会降低每个连接的安全设置,可能会对所有连接产生影响,并且我不确定它是否线程安全。

我建议将此类操作委托给每个请求的单独进程。

String content = new HttpsNoVerify.fetch(URL.create(myURL));

展示 com/example/HttpsNoVerify.java 的代码清单:

package com.example;

import org.apache.commons.io.IOUtils;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.net.URL;

public class HttpsNoVerify {
    public static void main(String... args) throws Exception {
        URL url = new URL(args[0]);

        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){}
            }
        };

        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

        IOUtils.copy(url.openStream(), System.out);
    }

    public String fetch(URL url) throws Exception {
        return new SubProcess(HttpsNoVerify.class).run(url.toString());
    }
}

这里是 com/example/SubProcess.java 的清单:

package com.example;

import org.apache.commons.io.IOUtils;

import java.util.Arrays;

public class SubProcess {
    private final Class<?> classToRun;

    public SubProcess(Class<?> classToRun) {
        this.classToRun = classToRun;
    }

    public String run(String... args) throws Exception {
        ProcessBuilder processBuilder = new ProcessBuilder("java",
                "-Djava.library.path=" + System.getProperty("java.library.path"),
                "-classpath", System.getProperty("java.class.path"),
                classToRun.getCanonicalName());

        for (String arg : args) processBuilder.command().add(arg);

        processBuilder.redirectErrorStream();

        Process process = processBuilder.start();

        String output = IOUtils.toString(process.getInputStream());

        process.waitFor();

        if (process.exitValue() != 0)
            throw new IllegalStateException(
                    String.format("Running %s with %s failed", classToRun, Arrays.toString(args)));

        return output;
    }
}

你认为 'certificate_unknown' 异常是客户端的问题,有什么想法为什么会抛出这个异常? - wuntee
1
@wuntee,我*强烈建议不要使用此TrustManager,因为它不会检查此客户端可能连接到的任何服务器证书的任何内容。相反,你可以使用我在答案中提出的变体,其中(a)只捕获CertificateExpiredException并且(b)在验证这是否是你想要的证书(来自chain[0])后,可能忽略它。 - Bruno
@wuntee @Bruno的TrustManager绝对比我在这里使用的no-op更可取。我会将我的基于进程的方法与他的TrustManager结合起来,以获得整体解决方案。 - Alain O'Dea
我本来想加入更多的逻辑,最初只是试图让它工作...谢谢。 - wuntee
@Alain,编写jSSLutils及其包装器的动机之一是能够使用现有的信任管理器(最小配置),同时能够捕获和处理某些情况和异常。我认为这样做只是使它稍微更容易使用,因为可以访问我的示例中的“origManager”(这将是在此处没有特定设置的那个)。 - Bruno
显示剩余3条评论

3
我不知道有什么属性可以让您忽略默认的X509TrustManager上的远程证书的时间有效性检查,但如果您可以访问客户端代码,则可能可以配置一个不同的SSLContext,并在其中使用自己的X509TrustManager,从而可以捕获此异常。
如果您想使用类似于jSSLutils和其SSLContextFactory这样的东西,您可以编写以下包装器:
PKIXSSLContextFactory sslContextFactory = new PKIXSSLContextFactory();
sslContextFactory.setTrustManagerWrapper(new X509TrustManagerWrapper() {
    @Override
    public X509TrustManager wrapTrustManager(final X509TrustManager origManager) {
        return new X509TrustManager() { 
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return origManager.getAcceptedIssuers();
            }

            @Override
            public void checkServerTrusted(X509Certificate[] chain,
                                                   String authType)
                    throws CertificateException {
                try {
                    origManager.checkServerTrusted(chain, authType);
                } catch (CertificateExpiredException e) {
                    // TODO log or do something else to rethrow
                                    // the exception if chain[0] isn't the certificate
                                    // for which you want to make this special case.
                }
            }

            @Override
            public void checkClientTrusted(X509Certificate[] chain,
                                                   String authType)
                    throws CertificateException {
                origManager.checkClientTrusted(chain, authType);
            }
        };
    }
});
SSLContext sslContext = sslContextFactory.buildSSLContext();

利用这个 SSLContext 真正取决于你的应用中使用 SSL 的情况。在最坏的情况下,你可以使用 Java 6 及以上版本的 SSLContext.setDefault(sslContext) 全局配置它。否则,一些库将允许你配置一个 SSLContext

1
这不是非常脆弱吗 - 如果在日期/时间检查之后进行另一个检查,它将被静默跳过? - dascandy
@dascandy,你说得完全正确。我完全忘记了这个答案,但我在这个类似的答案中提到了类似的内容。 - Bruno

-5

我认为你可以下载证书并将其添加到你的存储中。然后,你需要使用环境属性配置你的JVM,以指示存储的位置。


1
这已经是我正在做的事情了。问题是证书已过期,导致异常。我希望有一些属性可以设置为忽略过期的密钥。 - wuntee
添加这个证书不会解决问题,因为这个证书已经过期了。所以它无法通过验证。 - Znik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接