Java >> Java tutorial >  >> Tag >> HTTP

Forbruger en SOAP-webservice over HTTPS

I det forrige indlæg talte vi om at producere og forbruge en SOAP-webservice her. Dette indlæg vil være en efterfølger til det indlæg, da jeg for nylig stod over for et lignende problem under mit projekt. I dette indlæg vil vi tale om, hvordan man bruger en SOAP Webservice over HTTPS. Da dette vil være et lille indlæg, vil vi ikke sende nogen kode på GitHub.

Problem –

Mens du bruger en SOAP-webservice, som er bag SSL, vil du løbe ind i følgende fejl, hvis du ikke håndterer SSL-certifikater.


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)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1351)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:156)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:925)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:860)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1043)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1343)
at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:728)
at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123)
at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:138)
at SSLPoke.main(SSLPoke.java:31)
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:145)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:131)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
... 15 more

Løsning –

Denne fejl opstår dybest set, hvis din SOAP-webtjeneste er på SSL, og klienten forsøger at oprette forbindelse til webtjenesten, webtjenesten genkender ikke klienten og kaster denne fejl.

For at løse denne fejl kan du downloade et SSL-certifikat fra den server, hvor du er vært for SOAP-webtjenesten, og importere dette certifikat til din klientmaskines Keystore. I et produktionsmiljø bør du have en måde at få adgang til dette nøglelager, når der foretages et opkald til webtjenesten.

Lad os antage, at vores webservice fra posten er på SSL, f.eks. https://localhost:8943/benefits/endpoints/users.wsdl . Hvis du tilgår denne URL i browseren, vil du kunne se SSL-certifikatet. Eksporter dette SSL-certifikat i basis 64-formatfil, eksempel sslcertificate.crt . Importer dette certifikat i

keytool -import -alias sslcertificateofserver -keystore truststore.jks -storepass changeit -file sslcertificate.crt

Nu vil vi ændre den konfigurationsklasse, vi skrev for at konfigurere webservicekomponenter.


package com.betterjavacode.benefits.views;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;

@Configuration
public class ClientAppConfig
{
   private Resource getKeyStore()
   {
     Environment.getProperty("betterjavacode.com.keystore");
   }

   private String getKeystorePassword()
   {
     Environment.getProperty("betterjavacode.com.keyStorePassword");
   }

   @Bean
   public Jaxb2Marshaller marshaller()
   {
     Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
     marshaller.setContextPath("com.betterjavacode.benefits.soap");
     return marshaller;
   }

   @Bean
   public UserClient userClient(Jaxb2Marshaller marshaller) 
   {
     // WSDL URL - http://localhost:8080/benefits/endpoints/users.wsdl
     UserClient uc = new UserClient();
     uc.setDefaultUri("http://localhost:8080/benefits/endpoints/users.wsdl");
     uc.setMarshaller(marshaller);
     uc.setUnmarshaller(marshaller);

     FileInputStream fis = new FileInputStream(getKeyStore());
     KeyStore ks = KeyStore.getInstance("JKS");
     ks.load(fis, getKeyStorePassword().toCharArray());

     try 
     {
       fis.close();
     } 
     catch (IOException e) 
     {
     }
     KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
     keyManagerFactory.init(ks, keyStorePassword.toCharArray());

     FileInputStream fisTS = new FileInputStream(getKeyStore());
     KeyStore ts = KeyStore.getInstance("JKS");
     ts.load(fisTS, trustStorePassword.toCharArray());

     try 
     {
       fisTS.close();
     } 
     catch(IOException e) 
     {
     }
     TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
     trustManagerFactory.init(ts);

     HttpsUrlConnectionMessageSender messageSender = new HttpsUrlConnectionMessageSender();
     messageSender.setKeyManagers(keyManagerFactory.getKeyManagers());
     messageSender.setTrustManagers(trustManagerFactory.getTrustManagers());

     HostNameVerifier hv = new HostNameVerifier(){
        @Override
        public boolean verify( String hostname, SSLSession session)
        {
          return true;
        }
     }
     messageSender.setHostnameVerifier(hv);
     uc.setMessageSender(messageSender);
     return uc;
  } 
}

Denne ændring skulle rette fejlen om PKIX-stibygning mislykkedes .

Konklusion –

Afslutningsvis viste vi, hvordan man bruger en SOAP-webservice over HTTPS ved at tilføje Keystore og Truststore-check under kørsel.

Referencer

  • Forbrug af en SOAP-webtjeneste – Spring Boot

Java tag