Подтвердить что ты не робот

Загрузка пользовательского хранилища ключей в приложении Google App Engine Java

Я хочу открыть соединение HTTPS в приложении Google App Engine с помощью службы URLFetch. Чтобы иметь возможность проверить 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-сертификат?

UPDATE

В 2009 году разработчик App Engine Ник Джонсон из Google сказал https://groups.google.com/d/topic/google-appengine-python/C9RSDGeIraE/discussion:

API urlfetch не позволяет указать свой собственный клиент сертификаты, к сожалению, чего вы хотите достичь, не в настоящее время возможно.

Правильно ли это? Если каждый HTTP-запрос в App Engine зависит от URLFetch, это означает, что пользовательские сертификаты просто не могут использоваться вообще в GAE.

4b9b3361

Ответ 1

Вам следует зарегистрироваться как надежный тестер для Поддержка исходящих сокетов. В Желаемые функции они завершают SSL. Если будет поддерживаться больше частей API-интерфейса JDK SSL, создание чего-то вроде этого будет простым.

Ответ 2

Недавно я столкнулся с той же проблемой, и для меня работала реализация HttpClient, упакованная с appengine-api-stubs.

Зависимость Maven:

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

Но по той или иной причине механизм приложения не блокирует его.

Ответ 3

У меня была аналогичная проблема... Мне понадобился keystore.p12 для вызова внешней веб-службы, но у меня не было никакой возможности загрузить ее из пути к классам. Единственный способ, которым я мог его использовать, заключался в том, чтобы положить его, например. /WEB-INF/keystore.p12 и загрузите его оттуда.

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

Ответ 4

Я использую Appengine API 1.9.56 и то, что предложил Дима с помощью

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

больше не работает. Поэтому мне не нужна библиотека appengine-api-stubs.

Однако HttpsURLConnection.setDefaultSSLSocketFactory работает нормально.

Вот мое полное решение, которое решило мою проблему:

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

К счастью, HttpsURLConnection больше не занесен в черный список, как это было во время вопроса.