2012-01-25 13 views
6

Attualmente sto lavorando in un ambiente di test in cui il server ha un certificato SSL autofirmato predefinito. Sto usando Restlet 2.1-RC2 e istanziare risorsa cliente come questo:Come fare in modo che il client di Restlet ignori i problemi del certificato SSL

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

e il riutilizzo di client per ogni chiamata che faccio. Come posso impostare il client in modo che ignori i certificati problematici.

+2

No - Sono particolarmente chiedendo su come fare questo con il quadro Restlet (http://www.restlet.org/). Ho fatto questo in altre occasioni con altri tipi di connessioni, vorrei solo sapere il modo giusto di farlo con le scuse del Restlet – nwaltham

+0

, in qualche modo non l'ho capito .. – home

risposta

9

Il modo giusto è quello di importare questo certificato auto-firmato in negozio la fiducia del cliente, utilizzando keytool ad esempio:

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

È possibile farlo direttamente nel negozio di fiducia del JRE (lib/security/cacerts), che potrebbe non avere una certa flessibilità, o farlo nella propria copia di questo file, che poi si imposta come archivio fidato (la password predefinita è changeit o changeme su OSX). Si configura questa truststore a livello globale per l'applicazione utilizzando i soliti javax.net.ssl.trustStore* proprietà del sistema (ad esempio -Djavax.net.ssl.trustStore=mytruststore proprietà di sistema (e -Djavax.net.ssl.trustStorePassword) oppure è possibile configurarlo per un connettore specifico Restlet utilizzando i parametri di contesto del server, ad esempio:

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"); 

il modo sbagliato è quello di utilizzare un TrustManager che sta per disattivare qualsiasi verifica e passarlo attraverso un SslContextFactory (nell'estensione SSL). Qualcosa in questo senso.

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; } 
}); 

Mentre il primo metodo può sembrare un po 'più noioso del secondo (dal momento che è necessario ottenere prima il certificato del server e copiare i file), il secondo semplicemente farà scomparire i messaggi di errore non verificando nulla sul certificato del server, quindi rendendolo vulnerabile agli attacchi MITM attivi. Ciò si applica a qualsiasi connessione in cui è configurato questo SSLContext. (Questo "modo sbagliato non è sbagliato perché utilizza un personalizzato SSLContext, è sbagliato a causa di questa particolare configurazione del SSLContext.)

+0

Grazie mille.Una risposta molto completa! Purtroppo ora bloccato con javax.net.ssl.SSLException: il nome host nel certificato non corrisponde. E non c'è modo di aggirare questo: http://restlet.tigris.org/issues /show_bug.cgi?id=1078 – nwaltham

+2

Devo ammettere che non riesco a ricordare in cima alla mia testa come tw beccate la verifica del nome host. Il modo migliore è utilizzare un certificato autofirmato con il nome corretto. Spesso, l'impostazione del solo CN nel DN soggetto deve essere eseguita, ma è anche possibile impostare il Nome alt soggetto (sarà necessario se si utilizza comunque un indirizzo IP), vedere http://stackoverflow.com/a/8444863/372643 – Bruno

+0

Ho utilizzato un certificato autofirmato in Android, questa soluzione in combinazione con http://developer.android.com/training/articles/security-ssl.html#SelfSigned ha risolto il problema. Grazie mille! – user1226868

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