Проблема с DefaultHttpClient, сертификатами, Https и публикацией!

#java #android #post #https #certificate

#java #Android #Публикация #https #сертификат

Вопрос:

Мое приложение должно иметь возможность отправлять сообщения по протоколу https и сохранять сеанс, созданный с помощью файлов cookie. На данный момент у меня есть несколько разных способов решить проблему, и ни один из них не работает. В настоящее время я изучаю возможность использования DefaultHttpClient, потому что предполагается, что он автоматически сохраняет сеансы, созданные с помощью файлов cookie. Это избавляет меня от необходимости читать файл cookie и отправлять его вместе с любым другим сообщением. Однако, когда я пытаюсь опубликовать, используя имеющийся у меня код, публикация завершается ошибкой сертификата, которая указана ниже.

У меня была эта ошибка сертификата ранее с другим способом, которым я пытался решить проблему, и заставил ее работать с HttpsURLConnection, но это не сохраняет сеансы с файлами cookie автоматически.

Может кто-нибудь, пожалуйста, взглянуть на мой код и сказать мне, что я делаю не так, что я могу сделать лучше и что нужно изменить, чтобы это заработало.? СПАСИБО!!

Я пытался решить эту проблему в течение нескольких дней, и я узнаю, где. Каждый раз, когда я продвигаюсь немного дальше, меня отбрасывает еще дальше назад. Может кто-нибудь, пожалуйста, помочь мне! =)

 //my posting function
    private static String post(String urlString, List<NameValuePair> nameValuePairs)
    throws MalformedURLException, ProtocolException, IOException {
        DataOutputStream ostream = null;

        HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;

        DefaultHttpClient client = new DefaultHttpClient();

        SchemeRegistry registry = new SchemeRegistry();
        SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
        socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
        registry.register(new Scheme("https", socketFactory, 443));
        SingleClientConnManager mgr = new SingleClientConnManager(client.getParams(), registry);
        DefaultHttpClient http = new DefaultHttpClient(mgr, client.getParams());

        HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);

        HttpPost httppost = new HttpPost(urlString);

        httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

        HttpResponse response = http.execute(httppost);

        return response.toString();
}
  

 //the error
04-12 00:37:43.941: WARN/System.err(284): javax.net.ssl.SSLException: Not trusted server certificate
04-12 00:37:43.961: WARN/System.err(284):     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:371)
04-12 00:37:43.961: WARN/System.err(284):     at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:92)
04-12 00:37:43.970: WARN/System.err(284):     at org.apache.http.conn.ssl.SSLSocketFactory.createSocket(SSLSocketFactory.java:381)
04-12 00:37:43.980: WARN/System.err(284):     at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:164)
04-12 00:37:43.980: WARN/System.err(284):     at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
04-12 00:37:43.992: WARN/System.err(284):     at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
04-12 00:37:44.000: WARN/System.err(284):     at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:348)
04-12 00:37:44.000: WARN/System.err(284):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
04-12 00:37:44.000: WARN/System.err(284):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
04-12 00:37:44.020: WARN/System.err(284):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
04-12 00:37:44.020: WARN/System.err(284):     at cpe495.smartapp.SmartDBHelper.post(SmartDBHelper.java:208)
04-12 00:37:44.030: WARN/System.err(284):     at cpe495.smartapp.SmartDBHelper.authenticate(SmartDBHelper.java:105)
04-12 00:37:44.030: WARN/System.err(284):     at cpe495.smartapp.DataSender.submitData(DataSender.java:28)
04-12 00:37:44.040: WARN/System.err(284):     at cpe495.smartapp.DataSender.sendData(DataSender.java:21)
04-12 00:37:44.051: WARN/System.err(284):     at cpe495.smartapp.SmartApp$1.dataReceivedReceived(SmartApp.java:60)
04-12 00:37:44.061: WARN/System.err(284):     at cpe495.smartapp.ConnectDevice.fireDataReceivedEvent(ConnectDevice.java:287)
04-12 00:37:44.061: WARN/System.err(284):     at cpe495.smartapp.ConnectDevice.run(ConnectDevice.java:254)
04-12 00:37:44.071: WARN/System.err(284):     at java.lang.Thread.run(Thread.java:1096)
04-12 00:37:44.071: WARN/System.err(284): Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: TrustAnchor for CertPath not found.
04-12 00:37:44.090: WARN/System.err(284):     at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:168)
04-12 00:37:44.100: WARN/System.err(284):     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:366)
04-12 00:37:44.110: WARN/System.err(284):     ... 17 more
04-12 00:37:44.110: WARN/System.err(284): Caused by: java.security.cert.CertPathValidatorException: TrustAnchor for CertPath not found.
04-12 00:37:44.129: WARN/System.err(284):     at org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi.engineValidate(PKIXCertPathValidatorSpi.java:149)
04-12 00:37:44.150: WARN/System.err(284):     at java.security.cert.CertPathValidator.validate(CertPathValidator.java:202)
04-12 00:37:44.150: WARN/System.err(284):     at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:164)
04-12 00:37:44.150: WARN/System.err(284):     ... 18 more
  

Ответ №1:

Эта проблема связана с тем фактом, что клиентское приложение не может проверить создание пути к сертификату из привязки доверия (корневого доверенного центра сертификации) и сертификата SSL-сервера. Следовательно, этот сертификат не является надежным, и SSL-подтверждение не выполняется.

API apache HttpClient предоставляет приятную функцию, которая может вам помочь. SSLSocketFactory Конструктор может принимать KeyStore параметр, содержащий доверенные сертификаты.

Тогда вы можете:

  1. создайте файл KeyStore с keytool , содержащий либо сертификат корневого центра сертификации, либо сертификат сервера напрямую.
  2. добавьте это хранилище ключей в свое приложение
  3. создает SSLSocketFactory с помощью этого KeyStore

Все технические подробности и фрагменты кода вы можете прочитать в этом сообщении в блоге Боба Ли:http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html

Комментарии:

1. Как только у меня появится возможность, я попробую это решение. Я уже пробовал это однажды раньше, и это не сработало. Однако с тех пор я внес несколько изменений и попытаюсь снова. Спасибо

2. Эта ошибка также может возникнуть, если сервер не отправляет промежуточные сертификаты CA. В этом случае приложение не может присоединить цепочку сертификатов к якорю доверия.

3. Я выполнил три описанных выше шага, и иногда это работает, но чаще всего это не так. У вас есть какое-либо объяснение этому? Есть ли способ обойти это, поскольку это не мой сервер.