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

Проблемы с https (нет сертификата партнера) в android

Проблема

Я хочу отправить https-запрос на сайт https://10.2.20.20/fido/EzPay/login.php моего собственного сервера и получить от него ответ и сохранить его, например, в строке. Я нашел несколько примеров кода в Интернете и попытаюсь проверить их на предмет моей проблемы, но они не помогают. Ниже я представляю некоторые части кодов, которые я тестировал.


Пример кода:

Я пытаюсь использовать этот код, но всегда получаю одно и то же исключение "Нет сертификата партнера" Почему?

try
{
    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 httpClient = new DefaultHttpClient(mgr, client.getParams());

    // Set verifier      
    HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);

    // Example send http request
    final String url = "https://10.2.20.20/fido/EzPay/login.php";
    HttpPost httpPost = new HttpPost(url);
    HttpResponse response = httpClient.execute(httpPost);

    BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
    String line = "";
    while ((line = rd.readLine()) != null) {
        Log.i(DownloadImageTask.class.getName(), line);
    }

}
catch(IOException ex)
{
    Log.e(DownloadImageTask.class.getName(), ex.getMessage());
}

Exception.

03-02 16: 58: 25.234: W/System.err(1868): javax.net.ssl.SSLPeerUnverifiedException: Отсутствует сертификат peer 03-02 16: 58: 25,238: W/System.err(1868): при org.apache.harmony.xnet.provider.jsse.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:137) 03-02 16: 58: 25.238: W/System.err(1868): при org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:93) 03-02 16: 58: 25.238: W/System.err(1868): при org.apache.http.conn.ssl.SSLSocketFactory.createSocket(SSLSocketFactory.java:381) 03-02 16: 58: 25.238: W/System.err(1868): при org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:165) 03-02 16: 58: 25.250: W/System.err(1868): при org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164) 03-02 16: 58: 25.250: W/System.err(1868): при org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119) 03-02 16: 58: 25.250: W/System.err(1868): при org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360) 03-02 16: 58: 25.250: W/System.err(1868): при org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555) 03-02 16: 58: 25.250: W/System.err(1868): при org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487) 03-02 16: 58: 25.250: W/System.err(1868): при org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465) 03-02 16: 58: 25.250: W/System.err(1868): при com.https.test.DownloadImageTask.doInBackground(Https_testActivity.java:78) 03-02 16: 58: 25.250: W/System.err(1868): при com.https.test.DownloadImageTask.doInBackground(Https_testActivity.java:1) 03-02 16: 58: 25.250: W/System.err(1868): при android.os.AsyncTask $2.call(AsyncTask.java:264) 03-02 16: 58: 25.253: W/System.err(1868): при java.util.concurrent.FutureTask $Sync.innerRun(FutureTask.java:305) 03-02 16: 58: 25.253: W/System.err(1868): при java.util.concurrent.FutureTask.run(FutureTask.java:137) 03-02 16: 58: 25,253: W/System.err(1868): при android.os.AsyncTask $SerialExecutor $1.run(AsyncTask.java:208) 03-02 16: 58: 25,257: W/System.err(1868): при java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076) 03-02 16: 58: 25.257: W/System.err(1868): при java.util.concurrent.ThreadPoolExecutor $Worker.run(ThreadPoolExecutor.java:569) 03-02 16: 58: 25.257: W/System.err(1868): при java.lang.Thread.run(Thread.java:856)


Вопрос

Что я делаю неправильно и как я могу решить эту проблему. Почему я получаю исключение < Отсутствие сертификатов peer certificate "

Спасибо.

Edited


Настройки Windows Server.

<VirtualHost *:443>
  ServerName 10.2.20.20

 Alias /fido/EzPay/ "d:/fido/EzPay/" 
Alias /fido/EzPay "d:/fido/EzPay/" 

<Directory "d:/fido/EzPay/">
    Options Indexes FollowSymLinks MultiViews
    AllowOverride all
        Order allow,deny
    Allow from all
</Directory>


  # These are the actual SSL directives needed to get it all working!
  SSLEngine on
  SSLCertificateFile C:/wamp/bin/apache/apache2.2.17/conf/ssl/fidoserver.crt
  SSLCertificateKeyFile C:/wamp/bin/apache/apache2.2.17/conf/ssl/fidoserver.pem
</VirtualHost>
4b9b3361

Ответ 1

Наконец, я решил проблему https. Поскольку я воевал, основная проблема была в сервере, конкретно в сертификате. Android поддерживает только сертификат "BKS", и это было причиной того, что мы не можем получить ответ от сервер. Чтобы решить эту проблему, я прочитал более 30 статей и, наконец, нашел решение.

Действия, которые я предпринял для решения этой проблемы, вы можете увидеть ниже:

Первое, что я сделал, это генерировать файл .bks keystore из нашего сертификата fidoserver.crt, чтобы сделать это, я прочитал эту статью и делаю следующее:

  • Открыть cmd
  • Перейдите в папку JDK "cd X:\Programs\Java\Jdk6\bin"
  • Вызов следующей команды:

keytool -import -alias tomcat -file X://KeyStore/fidoserver.crt -keypass password - keystore X://KeyStore/keystore.bks -storetype BKS -storepass 222222 -providerClass org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath X://KeyStore/bcprov-jdk16-146.jar

Перед запуском этой команды я загрузил Bouncy Castle.jar и поместил его в папку с сертификатами. После выполнения всех этих шагов я получаю файл keystore.bks, который является правильным файлом сертификата для приложения Android. Я помещаю этот файл в папку Androids mnc/sdcard. В java-коде я написал следующий код, чтобы прочитать файл keystore.bbk

KeyStore trustStore  = KeyStore.getInstance( "BKS" /*KeyStore.getDefaultType()*/ );
FileInputStream instream = new FileInputStream(new File("/mnt/sdcard/keystore.bks"));
try {
    trustStore.load(instream, "222222".toCharArray());
} catch (NoSuchAlgorithmException e) {
    e.printStackTrace();
} catch (CertificateException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} finally {
    try { instream.close(); } catch (Exception ignore) {}
}

// Create socket factory with given keystore.
SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);

SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
Scheme sch = new Scheme("https", socketFactory, 443);
httpclient.getConnectionManager().getSchemeRegistry().register(sch);

HttpGet httpget = new HttpGet("https://10.2.20.20/fido/EzPay/login.php");

System.out.println("executing request " + httpget.getRequestLine());

HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();

System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
if (entity != null) {
    System.out.println("Response content length:  " + entity.getContentLength());
}

// Print html.
BufferedReader in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String line = "";
while ((line = in.readLine()) != null) {
     System.out.println(line);
}
in.close();

Все это позволяет m загрузить наш сертификат с заданным паролем 222222 (пароль, который мы даем при создании хранилища ключей с помощью keytool).

После этого все мое тестовое приложение начнет работать правильно. Теперь я могу отправить запрос на https и получить от него ответ. Я тестировал приложение с сервером FIDO, все отлично работает! Я думаю, что в понедельник я внесу некоторые изменения в приложении EzPay, и это начнет работать с https-соединениями.

Ссылки

Ответ 2

Метод запроса POST не подходит для URL-адреса /. Это все, что мы знаем.

Пример 1 не работает, потому что кажется, что вам не разрешено отправлять запрос POST на эту страницу. Попробуйте:

/* ... */
HttpGet httpGet = new HttpGet(url);
HttpResponse response = httpClient.execute(httpGet);
/* ... */

Пример 2 не работает, потому что вы не принимаете сертификат веб-сайта в качестве принятого сертификата, поэтому он также должен выглядеть следующим образом:

/* ... */
HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
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 httpClient = new DefaultHttpClient(mgr, client.getParams());
/* ... */

Ответ 3

Вы пытались открыть страницу в браузере? Если его неправильная конфигурация неправильная.

Обратите внимание, что если вы используете самоподписанный сертификат, у вас могут возникнуть проблемы с подключением. Некоторые версии ядра Android (до 2.6.32.9) не любят Self-Singed-Certificates.