We have a server running on Tomcat. This server connects to several third part services.
I developed and tested the connection to a SOAP service. This service requires the client to identify using a certificate. The first version set the properties:
- javax.net.ssl.trustStore
- javax.net.ssl.trustStorePassword
- javax.net.ssl.keyStore
- javax.net.ssl.keyStorePassword
- javax.net.ssl.keyStoreType
My code worked when tested alone, but when my code was integrated to our server, it messed up the connection to other third part servers. Looking for a solution to this problem, I found Apache CFX. I noted that this library has an API to set the certificates without the need to change global properties. We don´t use Spring and I would like to configure by code, but I am getting exceptions.
Code
public NotaFiscalServiceSoap getNotaFiscalServiceSoap() throws IOException, GeneralSecurityException {
if(notaFiscalServiceSoap==null){
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean() ;
factory.setWsdlURL(municipio.getUrlWsdl().toString());
factory.setServiceClass(NotaFiscalServiceSoap.class);
factory.setServiceName(Q_NAME);
factory.setConduitSelector(getConduitSelector());
notaFiscalServiceSoap = factory.create(NotaFiscalServiceSoap.class);
}
return notaFiscalServiceSoap;
}
private ConduitSelector getConduitSelector() throws IOException, GeneralSecurityException {
ServiceInfo serviceInfo = new ServiceInfo();
serviceInfo.setTargetNamespace(NAMESPACE);
EndpointInfo endpointInfo = new EndpointInfo();
endpointInfo.setService(serviceInfo);
endpointInfo.setName(Q_NAME);
endpointInfo.setAddress(municipio.getUrlWsdl().toString());
URLConnectionHTTPConduit conduit = new URLConnectionHTTPConduit(null, endpointInfo);
conduit.setTlsClientParameters(getTLSClientParameters());
ConduitSelector selector = new UpfrontConduitSelector(conduit);
return selector;
}
private TLSClientParameters getTLSClientParameters() throws GeneralSecurityException, IOException{
KeyStoreType trustKeyStore = new KeyStoreType();
trustKeyStore.setFile(pathCertWsdl);
trustKeyStore.setPassword(passCertWsdl);
trustKeyStore.setType("jks");
TrustManagersType trustManagerType = new TrustManagersType();
trustManagerType.setKeyStore(trustKeyStore);
KeyStoreType keyStoreType = new KeyStoreType();
keyStoreType.setFile(pathCertA1);
keyStoreType.setPassword(passCertA1);
keyStoreType.setType("pkcs12");
KeyManagersType keyManagerType = new KeyManagersType();
keyManagerType.setKeyStore(keyStoreType);
keyManagerType.setKeyPassword(passCertA1);
TLSClientParametersType clientParametersType = new TLSClientParametersType();
clientParametersType.setTrustManagers(trustManagerType);
clientParametersType.setKeyManagers(keyManagerType);
clientParametersType.setUseHttpsURLConnectionDefaultHostnameVerifier(true);
clientParametersType.setUseHttpsURLConnectionDefaultSslSocketFactory(true);
return TLSClientParametersConfig.createTLSClientParametersFromType(clientParametersType);
}
Exception
java.security.UnrecoverableKeyException: Password must not be null
at sun.security.provider.JavaKeyStore.engineGetKey(JavaKeyStore.java:132)
at sun.security.provider.JavaKeyStore$JKS.engineGetKey(JavaKeyStore.java:56)
at sun.security.provider.KeyStoreDelegator.engineGetKey(KeyStoreDelegator.java:96)
...
org.apache.cxf.service.factory.ServiceConstructionException: Failed to create service.
at org.apache.cxf.wsdl11.WSDLServiceFactory.<init>(WSDLServiceFactory.java:87)
at org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean.buildServiceFromWSDL(ReflectionServiceFactoryBean.java:394)
...
Caused by: javax.wsdl.WSDLException: WSDLException: faultCode=PARSER_ERROR: Problem parsing 'https://issonline.vilavelha.es.gov.br/SistemaIss/WebService/NotaFiscalService.asmx?WSDL'.: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at com.ibm.wsdl.xml.WSDLReaderImpl.getDocument(WSDLReaderImpl.java:2198)
at com.ibm.wsdl.xml.WSDLReaderImpl.readWSDL(WSDLReaderImpl.java:2390)
at com.ibm.wsdl.xml.WSDLReaderImpl.readWSDL(WSDLReaderImpl.java:2422)
...
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
...
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
at sun.security.validator.Validator.validate(Validator.java:260)
...
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
...
I found the solution to my problem.
I used this URL as reference: http://www.programcreek.com/java-api-examples/index.php?source_dir=support-examples-master/jaxws/cxfSsl.war/WEB-INF/classes/com/redhat/gss/jaxws/TestClient.java