2009-08-02 2 views
17

Ich versuche, einen SSL-Client zu schreiben, der Mail mit der javax.mail-API sendet. Das Problem, das ich habe, ist, dass der Server anfordert, dass ich SSL verwende, aber der Server ist auch mit einem Nicht-Standard-SSL-Zertifikat konfiguriert. Die Webseiten, die ich gefunden habe, sagen, dass ich das Zertifikat im Vertrauensspeicher installieren muss. Ich möchte das nicht tun (ich habe nicht die erforderlichen Berechtigungen.)Ist es möglich, dass Java den "Trust Store" ignoriert und einfach das SSL-Zertifikat akzeptiert, das es erhält?

  1. Gibt es eine Möglichkeit, Java dazu zu bringen, den Zertifikatfehler einfach zu ignorieren und zu akzeptieren?
  2. Fehlt das, gibt es eine Möglichkeit, den Truststore lokal für mein Programm zu haben, und nicht für die gesamte JVM installiert?
+0

Nur um zu klären, können Sie den Server-Code oder nur den Client ändern? –

+0

Das Ignorieren des Zertifikatsprüfungsschritts ist eine schlechte Idee. Es macht kaum einen Sinn, * heimlich * mit jemandem zu reden, wenn du nicht sicher bist, wer es ist. Option 2 (ein lokaler Trust Store) ist einfach zu verwenden. – Bruno

+1

Das Ignorieren des Bestätigungsschritts ist unter bestimmten Umständen problemlos möglich, z. B. wenn Sie sich in einem isolierten Netzwerk befinden und SSL aufgrund von Richtlinien nicht aktiviert ist, sondern weil Ihr Administrator nicht weiß, wie der Nicht-SSL-Dienst aktiviert werden soll . – vy32

Antwort

16

Sie müssen einen gefälschten TrustManager erstellen, der alle Zertifikate akzeptiert und als Zertifikat registriert Manager. So etwas wie dieses:

public class MyManager implements com.sun.net.ssl.X509TrustManager { 
    public boolean isClientTrusted(X509Certificate[] chain) { return true; } 
    public boolean isHostTrusted(X509Certificate[] chain) { return true; } 
    ... 
} 


com.sun.net.ssl.TrustManager[] managers = 
    new com.sun.net.ssl.TrustManager[] {new MyManager()}; 

com.sun.net.ssl.SSLContext.getInstance("SSL"). 
     .init(null, managers, new SecureRandom()); 
+6

All dies sollte wirklich mit der JSSE public API geschehen, anstatt die versteckten 'com.sun. *' Klassen zu optimieren. (Siehe so_mv antwort.) – Bruno

6

Versuchen Sie, diese (Antwort auf Frage 2):

System.setProperty("javax.net.ssl.trustStore", "/path/to/truststore"); 

Sie können dies auch als zusätzliche Befehlszeilenparameter angeben:

java -Djavax.net.ssl.trustStore=/path/to/truststore <remaining arguments> 

auf Fedora dies das gesamte System java sein könnte Trust Store in /etc/pki/java/cacerts

+1

gibt es eine Möglichkeit, "trust all" als 2. Argument in diesem wie * etc? –

+0

@UmerHayat Nein. Sie müssen wie in den anderen zwei Antworten codieren. –

21

Arbeitscode (in jdk1.6.0_23) für # 1.

Importe

import javax.net.ssl.HttpsURLConnection; 
import javax.net.ssl.SSLContext; 
import javax.net.ssl.TrustManager; 
import javax.net.ssl.X509TrustManager; 
import java.security.cert.X509Certificate; 

Die tatsächliche Vertrauen gesamten Code Trust.

TrustManager trm = new X509TrustManager() { 
    public X509Certificate[] getAcceptedIssuers() { 
     return null; 
    } 

    public void checkClientTrusted(X509Certificate[] certs, String authType) { 

    } 

    public void checkServerTrusted(X509Certificate[] certs, String authType) { 
    } 
}; 

SSLContext sc = SSLContext.getInstance("SSL"); 
sc.init(null, new TrustManager[] { trm }, null); 
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 
+0

Danke, das hat super für mich funktioniert. Das einzige Problem dabei ist, dass es die Einstellungen global so einstellt, dass es allen certs ... vertraut. Ein sicherer Ansatz könnte sein, die URLConnection wieder in eine HttpsURLConnection und die Call-setSSLSocketFactory dafür umzuwandeln.Nichtsdestotrotz ist dies eine GROSSE Antwort, mehrere andere sagten, es sei unmöglich, die Vertrauensüberprüfung zu umgehen und es war notwendig, ein Zertifikat hinzuzufügen oder einige JVM-Optionen zu optimieren. – Cervo

+4

Dies kann auch erforderlich sein, falls der Hostname nicht mit dem Zertifikat übereinstimmt: HostnameVerifier nullVerifier = new HostnameVerifier() { @Override public boolean überprüfen (String Hostname, SSLSession Sitzung) { return true; } }; HttpsURLConnection.setDefaultHostnameVerifier (nullVerifier); – seanf

1

Fügen Sie einfach -Dtrust_all_cert=true zu VM-Argumenten hinzu. Dieses Argument weist java an, alle Zertifikatsprüfungen zu ignorieren.

+0

Das ist ziemlich beängstigend, aber es scheint eine gute Antwort zu sein! Ich würde es gerne in Java machen und vielleicht ein bisschen mehr Kontrolle haben. – vy32

+6

Das ist kein VM-Argument und wird im Allgemeinen nicht funktionieren. –

-2

In CLI können Sie das Argument -noCertificationCheck zu Java hinzufügen, um die Zertifikatprüfungen zu ignorieren.

Verwandte Themen