2012-01-25 19 views
6

Actualmente estoy trabajando en un entorno de prueba donde el servidor tiene un certificado SSL autofirmado predeterminado. Estoy usando Restlet 2.1-RC2 y crear instancias de recursos del cliente como esto:Cómo hacer que el cliente de Restlet ignore los problemas del Certificado SSL

Client client = new Client(new Context(), Protocol.HTTP); 
cr = new ClientResource(String.format(itql_endpoint,riQuery)); 
cr.setNext(client); 

y la reutilización de cliente para cada llamada que hago. ¿Cómo puedo configurar el cliente para que ignore los certificados problemáticos?

+2

No - me siento particularmente preguntando acerca de cómo hacer esto con el marco Restlet (http://www.restlet.org/). He hecho esto en otras ocasiones con otros tipos de conexiones, solo me gustaría saber la forma correcta de hacerlo con Restlet – nwaltham

+0

Disculpas, de alguna manera no entendí eso ... . – home

Respuesta

9

La forma correcta es importar este certificado autofirmado en el almacén de confianza del cliente, utilizando keytool por ejemplo:

keytool -import -file server-cert.pem -alias myserver -keystore mytruststore.jks 

Puede hacerlo directamente en el almacén de confianza del JRE (lib/security/cacerts), que puede carecer de cierta flexibilidad, o hacerlo en su propia copia de este archivo, que luego configura como el almacén de confianza (la contraseña predeterminada es changeit o changeme en OSX). Configura este almacén de confianza a nivel mundial para su aplicación mediante los habituales javax.net.ssl.trustStore* propiedades del sistema (por ejemplo -Djavax.net.ssl.trustStore=mytruststore propiedad del sistema (y -Djavax.net.ssl.trustStorePassword) o se puede configurar para un conector específico en Restlet utilizando los parámetros de contexto del servidor, por ejemplo:

Series<Parameter> parameters = client.getContext().getParameters(); 
parameters.add("truststorePath", "/path/to/your/truststore.jks"); 
// parameters.add("truststorePassword", "password"); 
// parameters.add("trustPassword", "password"); 
// parameters.add("truststoreType", "JKS"); 

el camino equivocado es utilizar un TrustManager que va a desactivar cualquier verificación y pasarlo a través de un SslContextFactory (en la extensión SSL). Algo a lo largo de estas líneas.

TrustManager tm = new X509TrustManager() { 
    public void checkClientTrusted(X509Certificate[] chain, 
        String authType) 
        throws CertificateException { 
    } 

    public X509Certificate[] getAcceptedIssuers() { 
     return new X509Certificate[0]; 
    } 

    public void checkServerTrusted(X509Certificate[] chain, 
        String authType) 
        throws CertificateException { 
     // This will never throw an exception. 
     // This doesn't check anything at all: it's insecure. 
    } 
}; 

final SSLContext sslContext = SSLContext.getInstance("TLS"); 
sslContext.init(null, new TrustManager[] {tm}, null); 
Context context = client.getContext(); 
context.getAttributes().put("sslContextFactory", new SslContextFactory() { 
    public void init(Series<Parameter> parameters) { } 
    public SSLContext createSslContext() { return sslContext; } 
}); 

Aunque el primer método puede parecer un poco más tedioso que el segundo (ya que primero debe obtener el certificado del servidor y copiar los archivos), el segundo simplemente hará que los mensajes de error desaparezcan al no verificar nada sobre el certificado del servidor, por lo tanto haciéndolo vulnerable a los ataques MITM activos. Esto aplicará a cualquier conexión donde este SSLContext esté configurado. (Este "camino equivocado, no está mal, ya que utiliza una costumbre SSLContext, que es un error debido a esta configuración particular de la SSLContext.)

+0

Muchas gracias. ¡Una respuesta muy completa! Lamentablemente ahora está atrapado en javax.net.ssl.SSLException: el nombre de host en el certificado no coincide. Y parece que no hay forma de evitarlo: http://restlet.tigris.org/issues /show_bug.cgi?id=1078 – nwaltham

+2

Debo admitir que no puedo recordar la parte superior de mi cabeza cómo tw eak la verificación del nombre de host. La mejor manera es usar un certificado autofirmado con el nombre correcto. A menudo, configurar solo el CN ​​en el DN del Asunto debería funcionar, pero también puede establecer el Nombre Alt del Asunto (lo necesitará si usa una dirección IP de todos modos), consulte http://stackoverflow.com/a/8444863/372643. – Bruno

+0

Utilicé un certificado autofirmado en Android, esta solución en combinación con http://developer.android.com/training/articles/security-ssl.html#SelfSigned solucionó mi problema. Muchas gracias! – user1226868

1
// Create all-trusting host name verifier 
HostnameVerifier allHostsValid = new HostnameVerifier() { 
     public boolean verify(String hostname, SSLSession session) { 
     return true; 
     } 
    }; 
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid); 
Cuestiones relacionadas