2017-09-08 1 views
0

Ich versuche derzeit, eine Verbindung zu einem Server, der keinen Domain-Namen hat und ist nur erreichbar durch seine IP-Adresse. Ich habe es vorher versucht, indem ich den Bibliotheksalve benutzt habe, aber nach einem Tag Recherche konnte ich nicht herausfinden, warum der ssl-Handshake nicht funktionieren würde. nach dem Umschalten auf Okhttp bekam ich die Warnung:Okhttp 3 (Android): Verbinden mit IP-Adresse mit selbst signierten ssl

javax.net.ssl.SSLPeerUnverifiedException: Hostname 185.101.92.193 nicht überprüft:
Zertifikat: sha256/QMgPlAslWrBi1dd/P17AKxJCniO2RfHQ5MufVO5Xji4 =
DN: 1.2.840.113549.1.9. 1 = # 1619626c61636b6a61636b34323636323440676d61696c2e636f6d, CN = 185.101.92.193, O = Internet Widgits Pty Ltd, L = Berlin, ST = Berlin, C = DE
subjectAltNames []

Jetzt ist dieses Problem bereits auf github angesprochen : https://github.com/square/okhttp/issues/1467

Ich habe „gelöst“ das Problem mit dem folgenden Code (siehe HostnameVerifier an der Unterseite):

// loading CAs from an InputStream 
     try { 
      CertificateFactory cf = CertificateFactory.getInstance("X.509"); 
      InputStream cert = context.getResources().openRawResource(R.raw.servercert); 
      Certificate ca; 
      try { 
       ca = cf.generateCertificate(cert); 
      } finally { 
       cert.close(); 
      } 

      // creating a KeyStore containing our trusted CAs 
      String keyStoreType = KeyStore.getDefaultType(); 
      KeyStore keyStore = KeyStore.getInstance(keyStoreType); 
      keyStore.load(null, null); 
      keyStore.setCertificateEntry("ca", ca); 

      // creating a TrustManager that trusts the CAs in our KeyStore 
      String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); 
      TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); 
      tmf.init(keyStore); 

      // creating an SSLSocketFactory that uses our TrustManager 
      SSLContext sslContext = SSLContext.getInstance("TLS"); 
      sslContext.init(null, tmf.getTrustManagers(), null); 
      client = new OkHttpClient.Builder().sslSocketFactory(sslContext.getSocketFactory()) 
        .hostnameVerifier(new HostnameVerifier() { 
         @Override 
         public boolean verify(String s, SSLSession sslSession) { 
          if(s.equals(myIPAddress)){ 
           return true; 
          }else{ 
           return false; 
          } 
         } 
        }) 
        .build(); 
     }catch (Exception e){ 
      e.printStackTrace(); 
     } 

Jetzt sieht das ein bisschen wie schlechte Praxis für mich und meine eigentliche Frage ist: welche Probleme auftreten könnten von der Implementierung des HostnameVerifier wie folgt (Sicherheits-weise) und wie könnte ich diese Angelegenheit auf eine differenziertere Weise lösen?

+0

Sie könnten einen Domänennamen für den Server erhalten. Domain-Namen sind ziemlich billig. – CommonsWare

+0

ja, du hast einen Punkt. aber ich werde immer noch warten, wenn jemand mir sagen kann, warum ich nicht tun sollte, was ich hier getan habe, um das zu lernen. – Doflaminhgo

Antwort

2

Es gibt nichts mit dem Domain-Namen zu tun, das einzige Problem ist, dass Ihre Anwendung (Android) das Zertifikat nicht verifizieren kann, weil es privat ist (selbstsigniertes Zertifikat). In Ihrem Code haben Sie lediglich versucht, den Validierungsprozess zu umgehen, indem Sie die SSLFactory überschrieben und einen neuen erstellt haben, der Ihre Zertifizierungsstellen verwendet. Überprüfen Sie android Dokumentation unten: https://developer.android.com/training/articles/security-ssl.html#CommonProblems

Sie können fortfahren, was Sie haben. oder kaufen Sie ein Zertifikat und dann brauchen Sie diesen Code überhaupt nicht.

Verwandte Themen