I want to open a HTTPS connection in a Google App Engine app using the URLFetch service. To be able to verify the SSL certificate of the server my a
You should sign up as a trusted tester for Outbound sockets support. Under Desired Features they enlist SSL. If more parts of the JDK SSL API would be supported building something like this would be simple.
I have had a similar problem... I needed a keystore.p12
to call a foreign web service but had no chance loading it from the classpath. The only way I was able to use it was to put it in e.g. /WEB-INF/keystore.p12
and load it from there.
ServletContext context = getContext();
URL resourceUrl = context.getResource("/WEB-INF/keystore.p12");
I am using Appengine API 1.9.56 and what Dima suggested with
Protocol.registerProtocol("https",
new Protocol("https", (ProtocolSocketFactory) new SocketFactoryWrapper(sslContext.getSocketFactory()), 443));
is not working anymore. Therefore I do not need the appengine-api-stubs
library, either.
However, HttpsURLConnection.setDefaultSSLSocketFactory
just works fine.
Here is my complete solution which solved my problem:
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());
Luckily HttpsURLConnection
is not blacklisted anymore, as it was in the time the question was made.
I was recently facing the same issue and using the HttpClient implementation packaged with appengine-api-stubs worked for me.
Maven Dependency:
<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());
This does essentially the same thing as
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
But for one reason or another app engine doesn't block it.