2012-01-25 11 views
6

Obecnie pracuję w środowisku testowym, w którym serwer ma domyślny, samopodpisany certyfikat SSL. Korzystam z Restletu 2.1-RC2 i tworzenia wystąpienia zasobów klienta w następujący sposób:Jak sprawić, aby klient usługi Restlet ignorował problemy z certyfikatem SSL

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

i ponowne użycie klienta dla każdego wywołania, które wykonuję. Jak skonfigurować klienta, aby ignorował problematyczne certyfikaty.

+2

Nie - jestem szczególnie prosząc o tym, jak to zrobić z ram Restlet (http://www.restlet.org/). Robiłem to przy innych okazjach z innymi typami połączeń, chciałbym tylko wiedzieć, jak to zrobić z Restletem – nwaltham

+0

Przepraszam, jakoś tego nie zrozumiałem .. – home

Odpowiedz

9

Właściwy sposób jest import ten samopodpisany certyfikat do magazynu zaufanych klienta, korzystając keytool na przykład:

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

Można to zrobić bezpośrednio w magazynie zaufanych JRE'S (lib/security/cacerts) która może nie być elastyczna lub zrobić to we własnej kopii tego pliku, którą następnie ustawisz jako magazyn zaufanych certyfikatów (domyślne hasło to changeit lub changeme na OSX). Skonfigurowanie tego magazynu zaufanych certyfikatów globalnie dla aplikacji przy użyciu zwykłych javax.net.ssl.trustStore* właściwości systemowych (np -Djavax.net.ssl.trustStore=mytruststore właściwości systemu (i -Djavax.net.ssl.trustStorePassword) lub można go skonfigurować dla konkretnego złącza w Restlet za pomocą parametrów kontekst serwera, na przykład:

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

niewłaściwy sposób jest użycie TrustManager że zamierza wyłączyć żadnej weryfikacji i przekazać go za pośrednictwem SslContextFactory (w rozszerzeniu SSL). coś wzdłuż tych linii.

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

Podczas gdy pierwsza metoda może wydawać się nieco bardziej żmudna niż druga (ponieważ trzeba najpierw uzyskać certyfikat serwera i skopiować pliki), druga po prostu sprawi, że komunikaty o błędach znikną, nie weryfikując niczego na certyfikacie serwera, przez co czyniąc go podatnym na aktywne ataki MITM. Dotyczy to każdego połączenia, w którym skonfigurowano ten SSLContext. (Owa „niewłaściwy sposób nie jest źle, ponieważ używa niestandardowych SSLContext, to źle z powodu tej konkretnej konfiguracji SSLContext.)

+0

Bardzo dziękuję, bardzo kompletna odpowiedź! Niestety teraz utknęły w javax.net.ssl.SSLException: nazwa hosta w certyfikacie nie pasuje, i wydaje się, że nie ma odwrotu: http://restlet.tigris.org/issues /show_bug.cgi?id=1078 – nwaltham

+2

Muszę przyznać, że nie mogę sobie przypomnieć, jak to jest tw eak weryfikacja nazwy hosta. Najlepszym sposobem jest użycie samopodpisanego certyfikatu z poprawną nazwą. Często wystarczy ustawić CN w nazwie wyróżniającej podmiotu, ale można również ustawić Nazwę Alt obiektu (będzie ona potrzebna, jeśli mimo to korzystamy z adresu IP), patrz http://stackoverflow.com/a/8444863/372643 – Bruno

+0

Użyłem samopodpisanego certyfikatu w systemie Android, to rozwiązanie w połączeniu z http://developer.android.com/training/articles/security-ssl.html#SelfSigned naprawił mój problem. Dziękuję bardzo! – user1226868

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