在 Google App Engine Java 应用程序中加载自定义密钥存储

我想使用 URLFetch 服务在 Google App Engine 应用中打开 HTTPS 连接。为了能够验证我的应用程序正在与之通信的服务器的 SSL 证书,我正在使用我自己的密钥库文件。我想在加载应用程序时(即在执行任何HTTPS请求之前)在预热请求中读取此文件。密钥库文件是我的 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());

但是,我不能使用这种方法,因为虽然HttpURLConnection在GAE的JRE白名单上,但HttpsUrlConnection不在。

有没有另一种方法可以在 GAE 中使用自定义密钥库?我在GAE文档中没有找到任何有关这方面的信息。看起来虽然Google的URLFetch服务支持HTTPS,但密钥库无法自定义。这是正确的吗?

如果这是不可能的,那么这种方法在一般情况下是否仍然有效?或者是否有其他方法仍允许我验证 SSL 证书?

更新

2009年,谷歌的App Engine开发人员Nick Johnson在 https://groups.google.com/d/topic/google-appengine-python/C9RSDGeIraE/discussion 上说:

urlfetch API不允许您指定自己的客户端证书,因此不幸的是,您希望实现的目标目前是不可能的。

这还是正确的吗?如果 App Engine 中的每个 HTTP 请求都依赖于 URLFetch,这意味着自定义证书根本无法在 GAE 中使用。


答案 1

我最近遇到了同样的问题,使用与appengine-api-stubs打包的HttpClient实现对我有用。

Maven Dependency:

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

法典:

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

这基本上与

HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());

但是由于某种原因,应用程序引擎不会阻止它。


答案 2

您应该注册为受信任的测试人员,以获得出站套接字支持。在“所需功能”下,它们登记 SSL。如果支持JDK SSL API的更多部分,构建这样的东西将很简单。


推荐