Consuming HTTPS web service

Asked

Viewed 3,113 times

0

I’m trying to consume the zip code webservice

https://viacep.com.br/ws/88701001/json/

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 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.getSLException(Alerts.java:192) at sun.security.ssl.SLSocketImpl.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.SLSocketImpl.readRecord(Sslsocketimpl.java:1062) at sun.security.ssl.SLSocketImpl.performInitialHandshake(Sslsocketimpl.java:1375) at sun.security.ssl.SLSocketImpl.startHandshake(Sslsocketimpl.java:1403) at sun.security.ssl.SLSocketImpl.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 sun.net.www.protocol.http.HttpURLConnection.getInputStream(Httpurlconnection.java:1441) at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Httpsurlconnectionimpl.java:254) at br.com.transportesalvorada.security.Controll.Usuario_mb.main(Usuario_mb.java:141) Caused by: sun.security.Validator.Validatorexception: PKIX path failed building: 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) ... 13 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

As I understand it has no digital certificate, I really do not possess certificate.

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

  • I consume this webservice on my system and this also has no digital certificate.

3 answers

1


One way to solve 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 Factory that 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 is the certificate reading in 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 loadContextSSL is just call httpClient.execute and will no longer give the exception.

  • The code itself did not fit my problem. But your suggestion made me look for example of factury. Thank you very much. For the purpose of registering those facing the same problem please follow link. https://dzone.com/articles/how-setup-custom

  • Great! The idea is the same, only changes the client you use to make the calls to the service.

1

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

The code I use is the following:

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();
        }
}
  • Thanks Andrew. Without the certificate already helps. However I still don’t know how to make it work with HTTPS. Anyway thanks a lot.

1

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

The certificates are located in:

%JAVA_HOME%/lib/security/cacerts

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

Download the certificate by browser and with the help of the keytool you can add the certificate in your JVM where runs the server.

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

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

  • So I did, But the error Continues. See the listing C: certified temp>keytool -list Enter key storage area password: Key storage area type: JKS Key storage area provider: SUN Its key storage area contains 1 entry dawn, 06/23/2016, trustedCertEntry, Fingerprint (SHA1) certificate: E0:02:6F:9B:4B:55:7B:2F:42:1E:6A:09:35:5B:99:05:12:34:86:57 C: certified temp>

Browser other questions tagged

You are not signed in. Login or sign up in order to post.