Monday, February 07, 2011

Habilitando conexão Https c/ Java 'ignorando' o certificado

Frequentemente escrevo um código para realizar requisições entre aplicativos, seja para WS/REST ou mesmo um simples HttpClient, usando Https com Java. Como fazer uma requisição SSL sem registrar o certificado na JVM, ou mesmo um 'bypass' em certificado desconhecido?

Aqui deixo um exemplo de como realizar um requisição Https com Java ignorando o certificado. Usando X509TrustManager [mais sobre X509Certificate] e HostnameVerifier de fachada. Na verdade o uso do HostnameVerifier seria pra evitar java.io.IOException: HTTPS hostname wrong: should be ..., já que o nome do certificado não bate com o domínio.

package br.com.yaw.client.ssl.main;

import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
//...

public class TestSecureRequest {

  public static void main(String[] args) throws Exception  {
    final X509TrustManager cert = new X509TrustManager() {
      public X509Certificate[] getAcceptedIssuers() {
        return null;
      }
      
      public void checkServerTrusted(X509Certificate[] certs,
        String authType)
      throws java.security.cert.CertificateException {
        return;
      }
      
      public void checkClientTrusted(X509Certificate[] certs,
        String authType)
      throws java.security.cert.CertificateException {
        return;
      }
    };

    //cria socket ssl
    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, new TrustManager[] { cert }, null);

    //ativa o socket para a requisicao
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    
    final HostnameVerifier hv = new HostnameVerifier() {
      public boolean verify(String urlHostName, SSLSession session) {
        return true;
      }
    };

    HttpsURLConnection.setDefaultHostnameVerifier(hv);

    // daqui pra frente o codigo que acionar WS/REST, ou um simples HttpClient
    //...
  }
}

Peace of cake.

@edermag
http://www.yaw.com.br/

5 comments:

Genius said...

Olá,

Estou tentando realizar uma conexão ssl desta forma mas estou obtendo o seguinte erro: Exception in thread "main" java.net.SocketException: Software caused connection abort: recv failed

Marcelo said...

Cara, muito obrigado! Você me ajudou muito!

Unknown said...

Muito obrigado amigo, me foi e muita utilidade seu artigo

Wagner said...

Eder, valeu demais estava com problemas para reconhecer um servidor Web Service em REST e voce me salvou.

Unknown said...

Seu artigo foi perfeito para o que eu estava precisando. Muito Obrigado!