2010-06-22 6 views
27

Ich versuche, eine Verbindung zu einem meiner Server über SSL, mit Java. Ich habe versucht, hier eine Menge von Optionen ist mein bester Versuch:CertificateException: Kein Name gefunden ssl.someUrl.de gefunden

Ich erzeugen ein jssecacerts mit dem Skript Empfohlener: http://blogs.oracle.com/andreas/resource/InstallCert.java mit dem Befehl: java InstallCert ssl.someUrl.de

changeit

danach habe ich den Befehl ein zweites Mal: ​​

Loading KeyStore jssecacerts... 
Opening connection to ssl.someUrl.de:443... 
Starting SSL handshake... 

No errors, certificate is already trusted 

Server sent 1 certificate(s): 

1 Subject [email protected], CN=plesk, OU=Plesk, O=Parallels, L=Hernd 
on, ST=Virginia, C=US 
    Issuer [email protected], CN=plesk, OU=Plesk, O=Parallels, L=Hernd 
on, ST=Virginia, C=US 
    sha1 f1 0d 2c 54 05 e1 32 19 a0 52 5e e1 81 6c a3 a5 83 0d dd 67 
    md5  f0 b3 be 5e 5f 6e 90 d1 bc 57 7a b2 81 ce 7d 3d 

Enter certificate to add to trusted keystore or 'q' to quit: [1] 

ich die Datei in das Standardverzeichnis kopiert und ich lud das Zertifikat in Java trusts

System.setProperty("javax.net.ssl.trustStore", "C:\\Program Files (x86)\\Java\\jre6\\lib\\security\\jssecacerts"); 
System.setProperty("javax.net.ssl.trustStorePassword","changeit"); 

Dann versuche ich

URL url = new URL("https://ssl.someUrl.de/"); 
URLConnection conn = url.openConnection(); 
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); 

zu verbinden Und ich bekomme Fehler auf 3. Zeile: (Kein Name ssl.someUrl.de gefunden)

javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching ssl.someUrl.de found 

Ist dies Ursache für das Standard-Plesk-Zertifikat oder etwas anderes falsch?

Setup: JRE 6.20 Netbeans 6.8, Windows7 64bit

Antwort

39

Es sieht aus wie das Zertifikat des Servers, den Sie versuchen, eine Verbindung zu nicht seinen Hostnamen entsprechen.

Wenn ein HTTPS-Client eine Verbindung mit einem Server herstellt, wird überprüft, ob der Hostname im Zertifikat mit dem Hostnamen des Servers übereinstimmt. Es reicht nicht aus, dass ein Zertifikat vertrauenswürdig ist, es muss auch mit dem Server übereinstimmen, mit dem Sie sprechen möchten. (Als Analogie, auch wenn Sie vertrauen, dass ein Pass legitim ist, müssen Sie immer noch überprüfen, dass es derjenige für die Person ist, mit der Sie sprechen möchten, und nicht nur einen Pass, dem Sie vertrauen würden.)

In HTTP wird dies durch die Überprüfung durchgeführt, dass:

  • das Zertifikat enthält einen DNS alternativen Namen (das ist eine Standarderweiterung) Eintrag die Hostnamen übereinstimmt;

  • Wenn dies nicht der Fall ist, entspricht der letzte CN des Subjekts mit dem definierten Namen (dies ist der Hauptname, wenn Sie möchten) mit dem Hostnamen. (Siehe RFC 2818.)

Es ist schwer zu sagen, was das Thema alternative Name ist ohne das Zertifikat mit (obwohl, wenn Sie mit Ihrem Browser an und überprüfen ihren Inhalt in mehr Einzelheiten, sollten Sie in der Lage sein zu sehen, . it) Das Thema Distinguished Name scheint zu sein:

[email protected], CN=plesk, OU=Plesk, O=Parallels, L=Herndon, ST=Virginia, C=US 

(es wäre also CN = ssl.someUrl.de statt CN = plesk, sein müssen, wenn Sie mit keinen Betreff alternative Namen DNS: ssl.someUrl.de bereits, meine Vermutung ist, dass Sie nicht.)

Sie können die Überprüfung des Hostnamens möglicherweise umgehen, indem Sie HttpsURLConnection.setHostnameVerifier(..) verwenden. Es sollte nicht zu schwer sein, einen benutzerdefinierten HostnamenVerifier zu schreiben, der die Verifizierung unterstützt, obwohl ich vorschlagen würde, dies nur dann zu tun, wenn das Zertifikat hier speziell betroffen ist. Sie sollten das mithilfe des SSLSession-Arguments und seiner getPeerCertificates() -Methode ermitteln können.

(Außerdem müssen Sie nicht die javax.net.ssl ​​einzustellen. * Eigenschaften, wie Sie es getan haben, da man sowieso die Standardwerte verwenden.)

Alternativ kann, wenn Sie haben die Kontrolle über den Server, mit dem Sie sich verbinden, und sein Zertifikat. Sie können ein Zertifikat erstellen, das den oben genannten Regeln entspricht (CN sollte ausreichen, obwohl der alternative Name des Themas eine Verbesserung darstellt). Wenn ein selbstsigniertes Zertifikat für das, was Sie benennen, ausreicht, stellen Sie sicher, dass der allgemeine Name (CN) der Hostname ist, mit dem Sie sprechen möchten (keine vollständige URL, nur der Hostname).

+0

thx Ich tat es mit dem HostnameVerifier. Ich brauche nur eine verschlüsselte Verbindung. Es gibt nur einen Client und einen Server mit einer festen htts: // Adresse. – fehrlich

+1

Denken Sie daran, dass Sie eine Form der Identitätsüberprüfung der Verschlüsselung benötigen, um Sicherheit zu gewährleisten. Ansonsten ist es wie der Austausch von Geheimnissen mit jemandem, den Sie nicht kennen: Wie gut die Geheimhaltungsmethode auch ist, das schützt Sie nicht wirklich. – Bruno

+0

aber ich kenne den Server und den einzigen Client (der auf meinem Computer ist) und niemand kann den Datenstrom lesen. Und die https-Seite ist auch mit einem einfachen htaccess geschützt. Oder mache ich es falsch? – fehrlich

3

Ich habe eine gute Auflösung hier: http://www.mkyong.com/webservices/jax-ws/java-security-cert-certificateexception-no-name-matching-localhost-found/

Aber mein Problem war ein wenig anders und es anders gelöst.

Der Web-Dienst war auf dem Remote-Host. Zum Beispiel: https://some.remote.host/MyWebService?wsdl

Aber es war von IP für alle Kunden nur zur Verfügung, aber Zertifikat wurde für Domain erstellt: some.remote.host (CN = some.remote.host). Und diese Domain kann nicht per IP aufgelöst werden, da sie nicht in DNS dargestellt wird.

Also das gleiche Problem erschien: Wenn ich IP verwenden, um Verbindung zu Web-Service von ssl, kann nicht becase Zertifikat CN = some.remote.host erreicht werden und es ist nicht gleich Host-Namen, den ich angegeben habe (dh Host-IP).

ich beschlossen habe es durch diese Hostnamen mit IP-Anpassung in/etc/hosts-Datei. Das Problem wurde behoben.

Aber für den Fall, wenn der Web-Service auf localhost App-Server gehostet wird, denken sie, sollte es wie in seinem Artikel beschrieben gelöst werden mkyong.

1

sollte der Servernamen als Vor-/Nachname identisch sein, die Sie geben, während ein Zertifikat erstellen

15

In Java 8 Sie Servernamen überprüft mit dem folgenden Code überspringen kann: diese

HttpsURLConnection.setDefaultHostnameVerifier ((hostname, session) -> true); 

jedoch sollte nur in der Entwicklung verwendet werden!

+0

toll, danke. mehr Hilfe hier: http://www.mkyong.com/webservices/jax-ws/java-security-cert-certificateexception-no-name-matching-localhost-found/ – OhadR

7

Ich habe eine Methode fixUntrustCertificate(), so dass, wenn ich mit einer Domain zu tun habe, die nicht in vertrauenswürdigen Zertifizierungsstellen ist, können Sie das Verfahren vor der Anforderung aufzurufen. Dieser Code wird nach java1.4 funktionieren. Diese Methode gilt für alle Hosts:

public void fixUntrustCertificate() throws KeyManagementException, NoSuchAlgorithmException{ 


     TrustManager[] trustAllCerts = new TrustManager[]{ 
      new X509TrustManager() { 
       public java.security.cert.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, trustAllCerts, new java.security.SecureRandom()); 
     HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 

     HostnameVerifier allHostsValid = new HostnameVerifier() { 
      public boolean verify(String hostname, SSLSession session) { 
       return true; 
      } 
     }; 

     // set the allTrusting verifier 
     HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid); 
}