martes, 2 de marzo de 2010

Java: URL's seguras con certificados no confiables

Para acceder a una URL segura desde Java, se hace el mismo procedimiento que con una URL no segura:

URL url = new URL("https://www.urlsegura.com");
URLConnection conn = url.openConnection();

BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String linea;

while ((linea = in.readLine()) != null) 
  System.out.println(linea);
in.close();
Pero si esa URL segura tiene un certificado no confiable, el acceso a esa URL va a fallar, generando un error similar al siguiente:

sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Entonces lo que hay que hacer es instalar un TrustManager que no valide los certificados, en el Contexto SSL.
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
  public java.security.cert.X509Certificate[] getAcceptedIssuers() {
    return null;
}

public void checkClientTrusted( java.security.cert.X509Certificate[] certs, String authType) { }

public void checkServerTrusted( java.security.cert.X509Certificate[] certs, String authType) { }
}
};

try {
  SSLContext sc = SSLContext.getInstance("SSL");
  sc.init(null, trustAllCerts, new java.security.SecureRandom());
  HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

} catch (Exception e) { }

Una vez hecho esto ya podemos hacer lo del código de arriba sin que nos falle por certificados de seguridad.