Client WebService – Problema ao Conectar em WSDL com Certificado SSL

Esta é uma dica rápida para aqueles que estão tendo problemas ao consumir um WebService (WSDL) sobre uma camada  com certificado (SSL).  É comum se deparar com erros do tipo:

Caused by: javax.net.ssl.SSLHandshakeException: SSLHandshakeException
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
Caused by: javax.net.ssl.SSLHandshakeException: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty

Caso você esteja se deparando com este tipo de mensagem , será necessário atribuir o certificado do serviço como confiável na TrustStore do Java. (vide javax.net.ssl.trustStore). No exemplo a seguir vou considerar que você já possui uma keystore do Java com o certificado do serviço já importado (procure por posts no Google ensinando como pegar o certificado do site desejado e incluir dentro de uma KeyStore Java).

Na sua Classe, antes de disparar o consumo do WebService você poderá chamar um método por exemplo “setTrustManager()” para que este realize o byPass de confiar em todos os certificados configurados na sua Keystore. Ps: Atenção as 2 classes necessárias para a implementação do TrustManager.

          public static void setTrustManager() {
           try {
	        final String KEY_STORE = "CAMINHO_PARA_SUA_KEYSTORE"; //Exemplo: C:\certificado.jks";
		final String KEY_STORE_TYPE = "JKS";
		final String KEY_STORE_PASS = "SENHA_DA_SUA_KEYSTORE";
		    
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509","SunJSSE");
            KeyStore ks = KeyStore.getInstance(KEY_STORE_TYPE);
            File cert = new File(KEY_STORE);
            InputStream stream = new FileInputStream(cert);
            ks.load(stream, KEY_STORE_PASS.toCharArray());
            stream.close();
            kmf.init(ks,KEY_STORE_PASS.toCharArray());

            SSLContext context = SSLContext.getInstance("TLS");
            TrustEverythingTrustManager trustManager = new TrustEverythingTrustManager();
            context.init(kmf.getKeyManagers(),new TrustManager[] { trustManager }, new SecureRandom());
            SSLContext.setDefault(context);
	    HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
	    HttpsURLConnection.setDefaultHostnameVerifier(new AlwaysTrueHostnameVerifier());			
	   } catch (Exception e) {
	      throw new RuntimeException(e);
	   }
	}

        // Classe Acessória 
	public static class AlwaysTrueHostnameVerifier implements HostnameVerifier {
		@Override
		public boolean verify(String hostname, SSLSession session) {
			return true;
		}
	}

        // Classe Acessória 
        private static class TrustEverythingTrustManager implements X509TrustManager {
		
		@Override
		public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) throws CertificateException {}
		
		@Override
		public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) throws CertificateException {}

		@Override
		public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; }
	}

So, what do you think ?