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
プロセス全体に影響するため、デフォルトの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;
}
}
デフォルトの_X509TrustManager
_ sのリモート証明書の時間有効性チェックを無視できるプロパティについては知りませんが、クライアントコードにアクセスできる場合は、おそらく別の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を使用するものに大きく依存します。最悪の場合、SSLContext.setDefault(sslContext)
でJava 6以上を使用してグローバルに設定できます。それ以外の場合、一部のライブラリではSSLContext
を設定できます。