HTTPS Request mit unbekannter Instanz

Thallius

Top Contributor
Hi,

ich mache mit Java 8 einen HTTPS Request auf einen lokalen Server im Firmennetzwerk. Die Firma (Weltweit eine der größten Fimen überhaupt) hat eine eigene Zertifizierungs Instanz und hat dementsprechend für den Server ein Zertifikat ausgestellt.

Diese wird aber anscheinend von Java so nicht akzeptiert da Java die Instanz wohl nicht kennt.

So wie ich das nun herausgefunden habe, ist der einzige Weg, dass ich das Zertifikat lokal auf jedem Rechner in der keystroke der jeweiligen Java JVM installiere. Ist das wirklich der einzige Weg? Ich kann auch per Trick die Zertifizierungs-Validierung abschalten aber das ist ja auch keine wirklich akzeptabele Lösung.

Wenn ich wirklich das Zertifikat auf jedem Client Rechner installieren muss. Gibt es dafür fertige Frameworks die einen Installer für meine Java-Applikation darstellen die dann auch dieses Zertifikat mit installieren? Denn dieser sch... keystore kann ja bei jedem Client wo anders liegen. Je nachdem wo Java installiert ist etc.

Gruß

Claus
 

Tobse

Top Contributor
Da brauchst du keine andere Library. Mit HttpsURLConnection.setHostnameVerifier kannst du die Zertifikatsüberprüfung abschalten.

Geht das auch mit Sockets? Bei SSLSocket sehe ich auf den ersten Blick nichts

Und immer schön vorsichtig sein: die Prüfung abzuschalten ist eine Kardinalsünde. Wenn dann einen Decorator einbauen, mit dem man die CA des Unternehmens Whitelisten kann.
 

thecain

Top Contributor
Du könntest den Windows Keystore laden. Der Client müsste die Zertifikate da ja normalerweise haben.

Java:
KeyStore winKeystore = KeyStore.getInstance("Windows-MY", "SunMSCAPI");
 

Thallius

Top Contributor
Bitte schaut ein wenig über den Tellerrand. Wir haben in unserem weltweiten Konzern nicht nur Windows Clients! Alles was also eine reine Windows Lösung darstellt ist uninteressant. Oder glaubt ihr ich würde freiwillig Java programmieren wenn nicht Plattform Unabhängigkeit eine Grundvoraussetzung wäre ;)

Gruß

Claus
 

Tobse

Top Contributor
Also nochmal zum sicherstellen: du möchtest das mit den Java 8 boardmitteln erreichen? Und geht es um einfaches HTTPS Request&Response oder muss es eine Vollwertige TLS-Verbindung sein?
 

Thallius

Top Contributor
Also nochmal zum sicherstellen: du möchtest das mit den Java 8 boardmitteln erreichen? Und geht es um einfaches HTTPS Request&Response oder muss es eine Vollwertige TLS-Verbindung sein?

Ja und ja :) ich brauche nur einfachen https Request für ganz simplen JSON REST Service.

Also wenn es nicht anders geht, dann muss ich halt für Windows Mac und Linux jeweils einen extra installer schreiben aber das wäre die Notlösung.

Der Vorteil von java ist eben, dass man ohne irgendeine Installation nur durch starten der .jar eine applikation hat die auf jedem Rechner läuft.

Gruß

Claus
 

Tobse

Top Contributor
Man muss die Überprüfung nicht abschalten. Mit setHostnameVerifier kannst du jede beliebige Regel zur Überprüfung des Zertifikats implementieren.
Das hätte ich jetzt auch vorgeschlagen. Der Ansatz von @DrZoidberg funktioniert dafür einwandfrei. Den HostnameVerifier überschreiben und nur Zertifikate Akzeptieren, die vom speziellen CA signiert sind.

Man muss da mmn. aber sehr aufpassen: die normale Prüfung der Signaturen under der Hostnames muss natürlich wie gewohnt ablaufen. Am besten baut man wahrscheinlich einen Decorator um den HostnameVerifier, welcher mit dem Keystore des Systems/der JVM arbeitet.
 
Zuletzt bearbeitet:

Thallius

Top Contributor
Also ich komme überhaupt nicht weiter.

Aus lauter Verzweiflung habe ich jetzt mal mit dem HostNameVerifier rumprobiert aber der wird nicht einmal aufgerufen. Vorher kommt wohl schon die Exception

sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Mein Testcode:

Code:
    public static String[] sendPost(String url, String text) throws Exception 
    {
        final String USER_AGENT = "Mozilla/5.0";

        URL obj = new URL(url);
        BufferedReader in = null;
        String session = null;

        Logger.Log("HTTPS New Post Request: "+url);
        HttpsURLConnection.setDefaultHostnameVerifier(new MyHostNameVerifier()); // einfach mal probiert bringt aber auch nichts.

        Logger.Log("HTTPS New Post Request: "+url);
        HttpsURLConnection con;
        con = (HttpsURLConnection)obj.openConnection();
        Logger.Log("Connect build");
        con.setHostnameVerifier(new MyHostNameVerifier());
        Logger.Log("Verfier set"); // wird noch aufgerufen

        con.setConnectTimeout(5000);
        //add request header
        con.setRequestMethod("POST");
        con.setRequestProperty("User-Agent", USER_AGENT);
        con.setRequestProperty("Accept-Language", "en-US,en;q=0.5"); 

        // Send post request
        con.setDoOutput(true);

        DataOutputStream wr = new DataOutputStream(con.getOutputStream()); // Hier ist dann Feierabend und die Exc fliegt

        String urlParameters = text; 
        wr.writeBytes(urlParameters);
        wr.flush();
        wr.close();

        Logger.Log("Output send");

      ....
    }

public class MyHostNameVerifier implements HostnameVerifier
{
    @Override
    public boolean verify(final String hostName, final SSLSession session)
    {
        Logger.Log("SSL Hostname: "+hostName); // wird nicht aufgerufen
        return true;
    }
}

Was mache ich falsch?

Gruß

Claus
 

Tobse

Top Contributor
Also wenn der hier nichtmal aufgerufen wird, siehts glaub düster aus mit Bormitteln :/

Habe mich eben mal durch den Apache HTTP-Core gewühlt um die Stelle zu finden, wo da die TrustStrategies eingbaut werden. Es stellt sich heraus, dass die damit einen X509TrustManager zusammen bauen. Das selbst zu machen ist mmn. riskant, weil man dann auch die Signaturen selbst prüfen muss.

Von der HTTP-Core Library gibts inzwischen auch die nächste Major-Version (5), die einige der APIs, die ich da zum Whitelisten genutzt habe, wegen deprecation entfernt hat. In der 5er Version gibts vermutlich einen anderen Weg, das Whitelisting umzustetzen (das Interface TrustManager) gibts da noch.

Ich würde dir deshalb empfehlen, auf die Library zurück zu greiffen wenn die Lizensierung es erlaubt.
 

DrZoidberg

Top Contributor
Ich hab eine Lösung gefunden, die zu funktionieren scheint.
Dazu habe ich den Code von http://stackoverflow.com/questions/...certificate-checking-with-spring-resttemplate etwas verändert.
Solange du sicherstellst, dass die LocalHTTPS Klasse nur für lokale Server verwendet wird, brauchst du auch nur diese in der checkCertificates Methode zu prüfen.
Java:
class LocalHTTPS
{
  private static boolean checkCertificates(X509Certificate[] certs) {
    //...
    return true;
  }
  private static final HostnameVerifier LOCAL_HOSTNAME_VERIFIER = new HostnameVerifier()
  {
      @Override
      public boolean verify(final String hostName, final SSLSession session)
      {
          return true;
      }
  };
  private static final TrustManager[] LOCAL_TRUST_MANAGER = 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 ) throws CertificateException {
            if(certs == null || certs.length == 0 || authType == null || authType.length() == 0) {
              throw new IllegalArgumentException();
            }
            if(!checkCertificates(certs)) throw new CertificateException();
          }
      }
  };

  public static String[] sendPost(String url, String text) throws Exception {
      final String USER_AGENT = "Mozilla/5.0";

      URL obj = new URL(url);
      BufferedReader in = null;
      String session = null;

      Logger.Log("HTTPS New Post Request: "+url);
      HttpsURLConnection con;

      con = (HttpsURLConnection)obj.openConnection();
      SSLContext sc = SSLContext.getInstance("SSL");
      sc.init(null, LOCAL_TRUST_MANAGER, null);
      con.setSSLSocketFactory(sc.getSocketFactory());

      Logger.Log("Connect build");
      con.setHostnameVerifier(LOCAL_HOSTNAME_VERIFIER);
      Logger.Log("Verfier set");

      con.setConnectTimeout(5000);
      //add request header
      con.setRequestMethod("POST");
      con.setRequestProperty("User-Agent", USER_AGENT);
      con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");

      // Send post request
      con.setDoOutput(true);
      con.connect();
      DataOutputStream wr = new DataOutputStream(con.getOutputStream());

      String urlParameters = text;
      wr.writeBytes(urlParameters);
      wr.flush();
      wr.close();

      Logger.Log("Output send");
      return null;
    //....
  }
}
 

Thallius

Top Contributor
Lol

ich wollte quasi gerade auch eine vergleichbare Lösung posten die ich nun endlich gefunden habe.

TRotzdem Danke für Deine Mühen

Gruß

Claus
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
Developer_X Website HTML Code von HTTPS URL laden Allgemeine Java-Themen 0
P Java https proxy (-Dhttps.proxyHost) Start-Parameter funktioniert nicht? Allgemeine Java-Themen 2
F HTTPS Zertifikat Problem Allgemeine Java-Themen 3
OnDemand Filedownload von https-Seite Allgemeine Java-Themen 1
G https / SSL / Zertifikat Allgemeine Java-Themen 10
S svnkit Verbindung über https Anleitung Allgemeine Java-Themen 6
J Http/Https Geschwindigkeit Allgemeine Java-Themen 14
G Json POST-REQUEST Allgemeine Java-Themen 14
J Threads HTTP Request (Thread) dauert lange - in Android Allgemeine Java-Themen 3
T Basic Request von php zu Java Allgemeine Java-Themen 3
J Übergabe von post request Parametern Allgemeine Java-Themen 9
K http request get Allgemeine Java-Themen 2
W Request elevated rights (Vista) Allgemeine Java-Themen 9
A Threads zum Verringern der Latenzzeiten bei HTTP GET Request Allgemeine Java-Themen 8
G Array/String aus Request wieder in Array konvertieren Allgemeine Java-Themen 2
M Textdatei per Request lesen? Allgemeine Java-Themen 2
S HTTPUnit Test Fehler: Error on HTTP request: 500 Internal Er Allgemeine Java-Themen 9
S Klassen Einfügen von unbekannter menge an Variablen in eine Klasse mithilfe von ASM Allgemeine Java-Themen 5
D Unbekannter Fehler Allgemeine Java-Themen 1
C Best Practice Tiefe Kopie eines Arrays unbekannter Dimension und unbekannten Typs Allgemeine Java-Themen 4
E ArrayList mit unbekannter Größe Allgemeine Java-Themen 8
D Datentypen Typbestimmung unbekannter Wrapper-Klassen Allgemeine Java-Themen 5
G Exception mit unbekannter Quelle Allgemeine Java-Themen 11
S array von unbekannter größe Allgemeine Java-Themen 2
M Dynamisches ausführen von methoden unbekannter klassen Allgemeine Java-Themen 6

Ähnliche Java Themen

Neue Themen


Oben