Loading a custom key store in Google App Engine Java application

孤人 提交于 2019-11-28 21:17:15

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.

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!