Недавно я узнал о Google Cloud Messaging для Android, и я хотел интегрировать приложение для его использования. Я получил сторону Android от проекта, и приложение правильно зарегистрировано на сервере. Проблема в том, что мой сервер, похоже, не может аутентифицировать серверы GCM, чтобы он мог с ними разговаривать. Вот что я имею в виду:
В настоящее время мой сервер представляет собой простой Java-сервер SSL с хранилищем ключей и доверительным магазином. Truststore содержит ключ клиента (т.е. Ключ приложения) и наоборот, и клиент/сервер могут без проблем разговаривать друг с другом через SSL. Код, который я использую для отправки сообщения в приложение, следующий:
Sender sender = new Sender( "API_KEY" );
Message message = new Message.Builder().addData( "message", description ).build();
Result result = sender.send( message, ID, 1 );
Это дает мне следующее исключение:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Когда я запускаю свой сервер, я передаю имя trust/keystores и их пароли и загружаю их, чтобы их можно было использовать для общения с клиентом. Я подозреваю, что проблема в том, что в настоящее время доверительный магазин содержит только клиентский ключ, поэтому сервер может ТОЛЬКО говорить с клиентом и ни с кем другим. Это правильно, и если это так, у кого-нибудь есть идеи, как добавить сертификат GCM в доверительный магазин или что-то еще?
Большое спасибо, любая помощь очень ценится :)
PS Я попытался просто отправить сообщение клиенту, прежде чем загружать доверительный сервер на сервере, и приложение получило его успешно.
При использовании Google Cloud Messaging ваш сервер не разговаривает напрямую с клиентом. Сначала он проходит через "облачную" часть. Таким образом, установка клиентского сертификата в диспетчере доверия сервера не работает.
Вместо этого сервер должен будет проверить SSL-сертификат серверов Google Cloud Messaging. Они поддерживаются авторитетами сертификатов уже в вашем списке CA по умолчанию для ОС, поэтому отправка сообщения клиенту перед добавлением хранилища доверия будет работать нормально.
Догадаться. Как предположил kroot, проблема заключалась в том, что сервер не смог аутентифицировать серверы GCM, так как их сертификаты не были в его доверенности (я использовал свое собственное хранилище доверия, которое было открыто для хранилища доверия системы). Поэтому я изменил это, просто скопировав файл cacerts из папки безопасности Java, добавив в него специальный клиентский сертификат для приложения Android и используя этот файл в качестве моего хранилища доверия, так как он уже имеет сертификаты доверия по умолчанию для системы. Было достаточно просто, но мне потребовалось полдня, чтобы понять.
Я создал автономную java-программу, которая действовала как "сервер" и могла нажимать сообщение на сервер GCM, который, в свою очередь, мог доставлять сообщение в мое приложение для мобильных телефонов.
Мне не нужно было устанавливать какой-либо сертификат в файл jre\lib\security\cacerts, так как отправленных доверенных записей достаточно для подключения к серверу GCM.
Единственными зависимостями являются следующие
<dependency>
<groupId>com.google</groupId>
<artifactId>gcm-server</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
</dependency>
Сервер trustStore не доверяет сертификату клиента. Проверьте, что он содержит, и что вы действительно используете этот trustStore.