2012-10-24 21 views
20

Ich möchte eine HTTPS-Verbindung in einer Google App Engine-App mit dem Dienst URLFetch öffnen. Um das SSL-Zertifikat des Servers, mit dem meine App kommuniziert, mit zu überprüfen, verwende ich meine eigene Keystore-Datei. Ich möchte diese Datei in einer warmup request lesen, wenn meine App geladen ist, d. H. Bevor HTTPS-Anfragen ausgeführt werden. Die Schlüsselspeicherdatei ist Teil meiner WAR-Datei.Laden eines benutzerdefinierten Schlüsselspeichers in Google App Engine Java-Anwendung

TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType()); 
keystore.load(ClassLoader.getSystemResourceAsStream("myKeystoreFile"), "password".toCharArray()); 
trustManagerFactory.init(keystore); 

TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); 
SSLContext sslContext = SSLContext.getInstance("SSL"); 
sslContext.init(null, trustManagers, null); 

HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); 

ich diesen Ansatz nicht verwenden können, aber, weil während HttpURLConnection auf der JRE Whitelist des GAE ist, ist HttpsURLConnection nicht.

Gibt es eine andere Möglichkeit, einen benutzerdefinierten Schlüsselspeicher in GAE zu verwenden? Ich habe dazu in den GAE-Dokumenten keine Informationen gefunden. Es sieht so aus, als ob der URLFetch-Dienst von Google HTTPS unterstützt, der Keystore jedoch nicht angepasst werden kann. Ist das korrekt?

Wenn dies nicht möglich ist, ist der Ansatz generell noch gültig? Oder gibt es einen anderen Ansatz, der mir noch erlaubt, das SSL-Zertifikat zu überprüfen?

UPDATE

2009 App Engine-Entwickler Nick Johnson von Google sagte am https://groups.google.com/d/topic/google-appengine-python/C9RSDGeIraE/discussion:

Die urlfetch API Sie nicht erlauben, Ihre eigene Client Zertifikate angeben, so leider Was Sie erreichen möchten ist derzeit nicht möglich .

Ist das immer noch korrekt? Wenn jede HTTP (s) -Anfrage in App Engine auf URLFetch angewiesen ist, bedeutet dies, dass benutzerdefinierte Zertifikate in GAE überhaupt nicht verwendet werden können.

+0

Wie sich herausstellt, gibt es auf der [Google Code-Website von GAE] ein offenes Problem (http://code.google.com/p/googleappengine/issues/detail?id=3719). – Ingo

+1

Was wäre erforderlich, um dies auf App Engine zu unterstützen? ** Kann jemand von Google beschreiben, was getan werden müsste, um dies zu implementieren? ** – Ingo

+0

Leviticus sagt, dass er dies mit dem Apache HTTP Client implementiert hat, siehe http://esxx.blogspot.com/2009/06/using-apaches- httpclient-on-google-app.html. Ich versuche immer noch, seinen Ansatz zu verstehen. Hat jemand das versucht? Er stellte die Quelle in Subversion hier: http://svn.berlios.de/svnroot/repos/esxx/trunk/jee/org/esxx/js/protocol – Ingo

Antwort

3

Sie sollten Outbound sockets support für als trusted tester anmelden. Unter gewünschte Features sie SSL eintragen. Wenn mehr Teile der JDK-SSL-API unterstützt würden, wäre es einfach, so etwas zu erstellen.

0

Ich hatte ein ähnliches Problem ... Ich brauchte eine keystore.p12, um einen fremden Webdienst anzurufen, hatte aber keine Chance, ihn aus dem Klassenpfad zu laden. Der einzige Weg, wie ich es benutzen konnte, war, es z.B. /WEB-INF/keystore.p12 und von dort laden.

ServletContext context = getContext(); 
URL resourceUrl = context.getResource("/WEB-INF/keystore.p12"); 
+0

Vielleicht ist es ein Problem mit der Java-Richtlinie. Hast du die Richtliniendatei bearbeitet und alles erlaubt (als Test)? – djangofan

4

Ich war vor kurzem mit dem gleichen Problem konfrontiert und die Verwendung der HttpClient-Implementierung mit appengine-api-Stubs verpackt arbeitete für mich.

Maven Abhängigkeit:

<dependency> 
    <groupId>com.google.appengine</groupId> 
    <artifactId>appengine-api-stubs</artifactId> 
    <version>1.9.18</version> 
</dependency> 

Code:

// create SSL Context which trusts your self-signed certificate 
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType()); 
keystore.load(ClassLoader.getSystemResourceAsStream("myKeystoreFile"), "password".toCharArray()); 
trustManagerFactory.init(keystore); 
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); 
SSLContext sslContext = SSLContext.getInstance("SSL"); 
sslContext.init(null, trustManagers, null); 

// register your trusting SSL context 
Protocol.registerProtocol("https", 
     new Protocol("https", (ProtocolSocketFactory) new SocketFactoryWrapper(sslContext.getSocketFactory()), 443)); 

// make the https call 
HttpClient httpclient = new HttpClient(); 
GetMethod httpget = new GetMethod("https://myendpoint.com"); 
httpclient.executeMethod(httpget); 
System.out.println(httpget.getStatusLine()); 

Dies gilt im Wesentlichen dasselbe wie

HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); 

Aber aus einem Grund oder einer anderen App Engine es nicht blockiert .

0

Ich verwende appengine API 1.9.56 und was Dima vorgeschlagen mit

Protocol.registerProtocol("https", 
    new Protocol("https", (ProtocolSocketFactory) new SocketFactoryWrapper(sslContext.getSocketFactory()), 443)); 

nicht mehr funktioniert. Daher benötige ich die Bibliothek appengine-api-stubs auch nicht.

Aber HttpsURLConnection.setDefaultSSLSocketFactory funktioniert einfach gut.

Hier ist meine komplette Lösung, die mein Problem gelöst:

KeyStore keystore = KeyStore.getInstance("JKS"); 
    InputStream in = getClass().getResourceAsStream("/mytruststore.jks"); 
    keystore.load(in, "password".toCharArray()); 
    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
    trustManagerFactory.init(keystore); 
    TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); 
    SSLContext sslContext = SSLContext.getInstance("SSL"); 
    sslContext.init(null, trustManagers, null); 

    HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); 

Zum Glück HttpsURLConnection ist nicht mehr die schwarze Liste gesetzt, wie es in der Zeit war die Frage gestellt wurde.