Consume web service HTTPS

0

I'm trying to consume the CEP webservice

  

link

I'm using Java Web - JSF with WildfFly10

For this I am using the following code.

String URL_WEBSERVICECEP = "https://viacep.com.br/ws/[CEP]/json/";
String urlCep = URL_WEBSERVICECEP.replace("[CEP]", "88701650");
System.out.println("------ url : "+urlCep);
URL url = new URL(urlCep);
HttpsURLConnection con = (HttpsURLConnection)url.openConnection();
InputStream conS = con.getInputStream();

But this is giving the following error.

  

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) at   sun.security.ssl.Handshaker.fatalSE (Handshaker.java:296) at   sun.security.ssl.ClientHandshaker.serverCertificate (ClientHandshaker.java:1509)     at   sun.security.ssl.ClientHandshaker.processMessage (ClientHandshaker.java:216)     at sun.security.ssl.Handshaker.processLoop (Handshaker.java:979) at   sun.security.ssl.Handshaker.process_record (Handshaker.java:914) at   sun.security.ssl.SSLSocketImpl.readRecord (SSLSocketImpl.java:1062) at   sun.security.ssl.SSLSocketImpl.performInitialHandshake (SSLSocketImpl.java:1375)     at   sun.security.ssl.SSLSocketImpl.startHandshake (SSLSocketImpl.java:1403)     at   sun.security.ssl.SSLSocketImpl.startHandshake (SSLSocketImpl.java:1387)     at   sun.net.www.protocol.https.HttpsClient.afterConnect (HttpsClient.java:559)     at   sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect (AbstractDelegateHttpsURLConnection.java:185)     at   sun.net.www.protocol.http.HttpURLConnection.getInputStream0 (HttpURLConnection.java:1513)     at   html     at   sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream (HttpsURLConnectionImpl.java:254)     at   br.com.transportesalvorada.security.controll.Usuario_MB.main (User_MB.java:141)   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) 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:1491)     ... more 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)     at   sun.security.validator.PKIXValidator.doBuild (PKIXValidator.java:382)     ... 19 more

So I understand that you do not have the digital certificate, I do not really have a certificate.

The interesting thing is that if the direct test in the browser works.

    
asked by anonymous 23.06.2016 / 21:23

3 answers

1

One way to resolve this is to create a certificate factory to generate one that allows you to make calls to an https service. This is an example of the factory I created for certificates:

public class CustomSSLSocketFactory extends SSLSocketFactory {
private SSLContext sslContext = SSLContext.getInstance("TLS");

public CustomSSLSocketFactory(KeyStore truststore)
        throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
    super(truststore);
    TrustManager tm = gerarTrustManager();
    sslContext.init(null, new TrustManager[] { tm }, null);

}

private X509TrustManager gerarTrustManager() {
    return 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;
        }
    };
}

@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose)
        throws IOException, UnknownHostException {
    return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
}

@Override
public Socket createSocket() throws IOException {
    return sslContext.getSocketFactory().createSocket();
}

}

Here's the certificate reading on the http client:

protected void carregarContextoSSL(HttpClient httpClient) throws Exception {
    KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
    trustStore.load(null, null);
    SSLSocketFactory sf = new CustomSSLSocketFactory(trustStore);
    sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    httpClient.getConnectionManager().getSchemeRegistry().register(new Scheme(HTTPS, sf, 443));
}

After the method loadContextoSSL just call the httpClient.execute and it will not give the exception any more.

    
01.09.2016 / 03:05
1

Yes. If you test directly in the browser it will work because it manages the download of the certificate and your application does not.

Certificates are located at:

%JAVA_HOME%/lib/security/cacerts

To make it work, you must have the certificate. Since it is not self-signed, you can make a copy as follows:

Download the certificate from the browser and with the help of the keytool tool you can add the certificate to your JVM where the server runs.

keytool -import -noprompt -trustcacerts -alias -file -keystore -storepass

After importing the certificate, put it in cacerts check to see if it works.

    
23.06.2016 / 21:39
1

I consume this webservice on my system and I also do not have digital certificate.

The code I use is as follows:

public static Address consultaCep(String cep) throws MalformedURLException, IOException {
        Address e = new Address();
        String url = "http://viacep.com.br/ws/" + cep + "/json/";

        //Ler Json a partir da URL
        InputStream is = new URL(url).openStream();
        try {
            BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
            StringBuilder sb = new StringBuilder();
            int cp;
            while ((cp = rd.read()) != -1) {
                sb.append((char) cp);
            }
            String jsonText = sb.toString();
            Gson gson = new Gson();
            JsonObject json = gson.fromJson(jsonText, JsonObject.class);

            //vamos montar o endereço
            try{
                String erro = json.get("erro").getAsString();
                e.setZipCode(cep);
            } catch(Exception ex){
                //tem que entrar aqui, se não entrar é por que deu erro.
                e.setDistrict(json.get("bairro").getAsString());
                e.setZipCode(cep);
                e.setCity(json.get("localidade").getAsString());
                e.setState(json.get("uf").getAsString());
                e.setStreet(json.get("logradouro").getAsString());
            }
            return e;
        } finally {
            is.close();
        }
}
    
01.09.2016 / 03:12