java google-app-engine https keystore urlfetch

Cargar un almacén de claves personalizado en la aplicación Java de Google App Engine



google-app-engine https (4)

Debe registrarse como un comprobador de confianza para el soporte de sockets de salida . En las características deseadas , solicitan SSL. Si se admitieran más partes de la API JDK SSL, construir algo así sería simple.

Quiero abrir una conexión HTTPS en una aplicación de Google App Engine utilizando el servicio URLFetch . Para poder verificar el certificado SSL del servidor con el que mi aplicación está hablando, estoy usando mi propio archivo de almacén de claves . Quiero leer este archivo en una solicitud de preparación cuando se carga mi aplicación, es decir, antes de realizar cualquier solicitud HTTPS. El archivo de almacén de claves es parte de mi archivo WAR.

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());

No puedo utilizar este enfoque, sin embargo, porque mientras HttpURLConnection está en la lista blanca JRE de GAE, HttpsUrlConnection no lo está.

¿Hay alguna otra manera de usar un almacén de claves personalizado en GAE? No encontré información sobre esto en los documentos de GAE. Parece que, aunque el servicio URLFetch de Google admite HTTPS, el almacén de claves no se puede personalizar. ¿Es esto correcto?

Si esto no es posible, ¿el enfoque sigue siendo válido en general? ¿O hay un enfoque diferente que todavía me permite verificar el certificado SSL?

ACTUALIZAR

En 2009, el desarrollador de App Engine Nick Johnson de Google dijo en https://groups.google.com/d/topic/google-appengine-python/C9RSDGeIraE/discussion :

La API de urlfetch no le permite especificar sus propios certificados de cliente, por lo tanto, desafortunadamente, lo que quiere lograr no es posible actualmente.

¿Esto sigue siendo correcto? Si cada solicitud de HTTP (s) en App Engine se basa en URLFetch, esto significaría que los certificados personalizados simplemente no se pueden usar en GAE.


Estoy usando Appengine API 1.9.56 y lo que Dima sugirió con

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

ya no funciona Por lo tanto, tampoco necesito la appengine-api-stubs .

Sin embargo, HttpsURLConnection.setDefaultSSLSocketFactory funciona bien.

Aquí está mi solución completa que resolvió mi problema:

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());

Afortunadamente, HttpsURLConnection ya no está en la lista negra, como lo fue en el momento en que se hizo la pregunta.


Hace poco me enfrenté al mismo problema y me fue útil utilizar la implementación de HttpClient empaquetada con appengine-api-stubs.

Dependencia de Maven:

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

Código:

// 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());

Esto hace esencialmente lo mismo que

HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());

Pero por una razón u otra, el motor de la aplicación no lo bloquea.


Tuve un problema similar ... Necesitaba un keystore.p12 para llamar a un servicio web extranjero pero no tuve la oportunidad de cargarlo desde el classpath. La única forma en que pude usarlo fue ponerlo en eg /WEB-INF/keystore.p12 y cargarlo desde allí.

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