прием HTTPS-соединений с самозаверяющими сертификатами

153

Я пытаюсь установить HTTPS-соединения, используя HttpClientlib, но проблема в том, что, поскольку сертификат не подписан признанным центром сертификации (CA), таким как Verisign , GlobalSIgn и т. Д., Перечисленным в наборе доверенных сертификатов Android, Я продолжаю получать javax.net.ssl.SSLException: Not trusted server certificate.

Я видел решения, в которых вы просто принимаете все сертификаты, но что, если я хочу спросить пользователя?

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

Morten
источник
Это принятое решение сработало для me- stackoverflow.com/questions/2642777/…
Venkatesh

Ответы:

171

Первое, что вам нужно сделать, это установить уровень проверки. Таких уровней не так уж много:

  • ALLOW_ALL_HOSTNAME_VERIFIER
  • BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
  • STRICT_HOSTNAME_VERIFIER

Хотя метод setHostnameVerifier () устарел для новой библиотеки apache, но для версии в Android SDK это нормально. И поэтому мы берем ALLOW_ALL_HOSTNAME_VERIFIERи устанавливаем его в фабрике методов SSLSocketFactory.setHostnameVerifier().

Далее вам нужно установить нашу фабрику для протокола на https. Для этого просто вызовите SchemeRegistry.register()метод.

Тогда вам нужно создать DefaultHttpClientс SingleClientConnManager. Также в приведенном ниже коде вы можете видеть, что по умолчанию также будет использоваться наш флаг ( ALLOW_ALL_HOSTNAME_VERIFIER) по методуHttpsURLConnection.setDefaultHostnameVerifier()

Ниже код работает для меня:

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://encrypted.google.com/";
HttpPost httpPost = new HttpPost(url);
HttpResponse response = httpClient.execute(httpPost);
Николай Москвин
источник
6
Я не могу заставить этот код работать, к сожалению, я все еще получаю «Ненадежный сертификат сервера». Есть ли какие-то дополнительные разрешения, которые я должен установить, чтобы это работало?
Юрий
1
Разве этот код не принимает все сертификаты? Мне нужно всплывающее окно, чтобы принять это.
Мортен
3
Я использую, org.apache.http.conn.ssl.SSLSocketFactoryпочему я хочу использовать javax.net.ssl.HttpsURLConnection??
Кто-то где-то
9
Можете ли вы объяснить, чем этот код лучше, чем полностью отключить проверку сертификата? Я не знаком с ssl API от Android, но на первый взгляд это кажется совершенно небезопасным для активных злоумышленников.
CodesInChaos
3
Я бы предложил использовать ThreadSafeClientConnManager вместо SingleClientConnManager
Farm
124

Следующие основные шаги необходимы для обеспечения защищенного соединения от центров сертификации, которые не считаются доверенными для платформы Android.

По просьбе многих пользователей, я отразил самые важные части из моей статьи в блоге здесь:

  1. Получите все необходимые сертификаты (root и любые промежуточные CA)
  2. Создайте хранилище ключей с помощью keytool и поставщика BouncyCastle и импортируйте сертификаты
  3. Загрузите хранилище ключей в ваше приложение для Android и используйте его для защищенных соединений (я рекомендую использовать Apache HttpClient вместо стандартного java.net.ssl.HttpsURLConnection(проще для понимания, более производительным)

Хватай сертификаты

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

Создать хранилище ключей

Загрузите BouncyCastle Provider и сохраните его в известном месте. Также убедитесь, что вы можете вызвать команду keytool (обычно находится в папке bin вашей установки JRE).

Теперь импортируйте полученные сертификаты (не импортируйте сертификат конечной точки) в отформатированное хранилище ключей BouncyCastle.

Я не проверял это, но я думаю, что порядок импорта сертификатов важен. Это означает, что сначала нужно импортировать самый нижний сертификат промежуточного ЦС, а затем весь путь до сертификата корневого ЦС.

С помощью следующей команды будет создано новое хранилище ключей (если оно еще не существует) с паролем mysecret и будет импортирован сертификат промежуточного ЦС. Я также определил поставщика BouncyCastle, где его можно найти в моей файловой системе и в формате хранилища ключей. Выполните эту команду для каждого сертификата в цепочке.

keytool -importcert -v -trustcacerts -file "path_to_cert/interm_ca.cer" -alias IntermediateCA -keystore "res/raw/mykeystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "path_to_bouncycastle/bcprov-jdk16-145.jar" -storetype BKS -storepass mysecret

Проверьте, правильно ли были импортированы сертификаты в хранилище ключей:

keytool -list -keystore "res/raw/mykeystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "path_to_bouncycastle/bcprov-jdk16-145.jar" -storetype BKS -storepass mysecret

Должен выводить всю цепочку:

RootCA, 22.10.2010, trustedCertEntry, Thumbprint (MD5): 24:77:D9:A8:91:D1:3B:FA:88:2D:C2:FF:F8:CD:33:93
IntermediateCA, 22.10.2010, trustedCertEntry, Thumbprint (MD5): 98:0F:C3:F8:39:F7:D8:05:07:02:0D:E3:14:5B:29:43

Теперь вы можете скопировать хранилище ключей как необработанный ресурс в ваше приложение для Android под res/raw/

Используйте хранилище ключей в вашем приложении

Прежде всего мы должны создать пользовательский Apache HttpClient, который использует наше хранилище ключей для соединений HTTPS:

import org.apache.http.*

public class MyHttpClient extends DefaultHttpClient {

    final Context context;

    public MyHttpClient(Context context) {
        this.context = context;
    }

    @Override
    protected ClientConnectionManager createClientConnectionManager() {
        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        // Register for port 443 our SSLSocketFactory with our keystore
        // to the ConnectionManager
        registry.register(new Scheme("https", newSslSocketFactory(), 443));
        return new SingleClientConnManager(getParams(), registry);
    }

    private SSLSocketFactory newSslSocketFactory() {
        try {
            // Get an instance of the Bouncy Castle KeyStore format
            KeyStore trusted = KeyStore.getInstance("BKS");
            // Get the raw resource, which contains the keystore with
            // your trusted certificates (root and any intermediate certs)
            InputStream in = context.getResources().openRawResource(R.raw.mykeystore);
            try {
                // Initialize the keystore with the provided trusted certificates
                // Also provide the password of the keystore
                trusted.load(in, "mysecret".toCharArray());
            } finally {
                in.close();
            }
            // Pass the keystore to the SSLSocketFactory. The factory is responsible
            // for the verification of the server certificate.
            SSLSocketFactory sf = new SSLSocketFactory(trusted);
            // Hostname verification from certificate
            // http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506
            sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
            return sf;
        } catch (Exception e) {
            throw new AssertionError(e);
        }
    }
}

Мы создали наш собственный HttpClient, теперь мы можем использовать его для безопасных соединений. Например, когда мы делаем вызов GET для ресурса REST:

// Instantiate the custom HttpClient
DefaultHttpClient client = new MyHttpClient(getApplicationContext());
HttpGet get = new HttpGet("https://www.mydomain.ch/rest/contacts/23");
// Execute the GET call and obtain the response
HttpResponse getResponse = client.execute(get);
HttpEntity responseEntity = getResponse.getEntity();

Это оно ;)

саксофон
источник
8
Это полезно только для получения сертификатов перед отправкой приложения. Не очень помогает пользователям принимать свои собственные сертификаты. для вашего приложения
Fuzzy
Привет всем, может кто-нибудь сказать мне процесс проверки для хранилища ключей с хранилищем доверенных сертификатов для вышеупомянутой реализации ??? заранее спасибо ..
andriod_testing
Это сработало нормально ... но теперь я сталкиваюсь с проблемой, когда я перезаписываю сертификат на сервере. Кажется странным, что каждый раз, когда я обновляю сертификат на моем сервере, хранилище на стороне клиента также должно обновляться. Должен быть лучший способ: |
БПН
Ответ Gr8, я бы предложил использовать ThreadSafeClientConnManager вместо SingleClientConnManager
Ферма
Я добавил /res/raw/mykeystore.bks, хотя и не смог разрешить ссылку на него. как это решить?
uniruddh
16

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

Поместите *.crtфайл сертификата /res/rawтак, чтобы он был доступен изR.raw.*

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

package com.example.customssl;

import android.content.Context;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;

public class CustomCAHttpsProvider {

    /**
     * Creates a {@link org.apache.http.client.HttpClient} which is configured to work with a custom authority
     * certificate.
     *
     * @param context       Application Context
     * @param certRawResId  R.raw.id of certificate file (*.crt). Should be stored in /res/raw.
     * @param allowAllHosts If true then client will not check server against host names of certificate.
     * @return Http Client.
     * @throws Exception If there is an error initializing the client.
     */
    public static HttpClient getHttpClient(Context context, int certRawResId, boolean allowAllHosts) throws Exception {


        // build key store with ca certificate
        KeyStore keyStore = buildKeyStore(context, certRawResId);

        // init ssl socket factory with key store
        SSLSocketFactory sslSocketFactory = new SSLSocketFactory(keyStore);

        // skip hostname security check if specified
        if (allowAllHosts) {
            sslSocketFactory.setHostnameVerifier(new AllowAllHostnameVerifier());
        }

        // basic http params for client
        HttpParams params = new BasicHttpParams();

        // normal scheme registry with our ssl socket factory for "https"
        SchemeRegistry schemeRegistry = new SchemeRegistry();
        schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        schemeRegistry.register(new Scheme("https", sslSocketFactory, 443));

        // create connection manager
        ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);

        // create http client
        return new DefaultHttpClient(cm, params);
    }

    /**
     * Creates a {@link javax.net.ssl.HttpsURLConnection} which is configured to work with a custom authority
     * certificate.
     *
     * @param urlString     remote url string.
     * @param context       Application Context
     * @param certRawResId  R.raw.id of certificate file (*.crt). Should be stored in /res/raw.
     * @param allowAllHosts If true then client will not check server against host names of certificate.
     * @return Http url connection.
     * @throws Exception If there is an error initializing the connection.
     */
    public static HttpsURLConnection getHttpsUrlConnection(String urlString, Context context, int certRawResId,
                                                           boolean allowAllHosts) throws Exception {

        // build key store with ca certificate
        KeyStore keyStore = buildKeyStore(context, certRawResId);

        // Create a TrustManager that trusts the CAs in our KeyStore
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);

        // Create an SSLContext that uses our TrustManager
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, tmf.getTrustManagers(), null);

        // Create a connection from url
        URL url = new URL(urlString);
        HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
        urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());

        // skip hostname security check if specified
        if (allowAllHosts) {
            urlConnection.setHostnameVerifier(new AllowAllHostnameVerifier());
        }

        return urlConnection;
    }

    private static KeyStore buildKeyStore(Context context, int certRawResId) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
        // init a default key store
        String keyStoreType = KeyStore.getDefaultType();
        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);

        // read and add certificate authority
        Certificate cert = readCert(context, certRawResId);
        keyStore.setCertificateEntry("ca", cert);

        return keyStore;
    }

    private static Certificate readCert(Context context, int certResourceId) throws CertificateException, IOException {

        // read certificate resource
        InputStream caInput = context.getResources().openRawResource(certResourceId);

        Certificate ca;
        try {
            // generate a certificate
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            ca = cf.generateCertificate(caInput);
        } finally {
            caInput.close();
        }

        return ca;
    }

}

Ключевые моменты:

  1. Certificate объекты генерируются из .crt файлов.
  2. По умолчанию KeyStore создано.
  3. keyStore.setCertificateEntry("ca", cert)добавляет сертификат в хранилище ключей под псевдонимом "ca". Вы модифицируете код, чтобы добавить больше сертификатов (промежуточный CA и т. Д.).
  4. Основная цель - создать объект, SSLSocketFactoryкоторый затем может быть использован HTTPClientили HttpsURLConnection.
  5. SSLSocketFactory можно настроить далее, например, чтобы пропустить проверку имени хоста и т. д.

Более подробная информация по адресу: http://developer.android.com/training/articles/security-ssl.html

SD
источник
Где я могу получить .crtфайлы? Скачать с сервера?
zionpi
@zionpi Файл сертификата будет таким же, как и сервер с поддержкой TLS, к которому вы подключаетесь.
SD
Спасибо! Это было так легко!
Капил Тадани
@SD Как я могу использовать файл .P12 вместо .crt?
Ракеш Р Наир
Я такой же сомнения холодно вы помочь stackoverflow.com/questions/57389622/...
StezPet
8

Я был разочарован, пытаясь подключить мое Android-приложение к моей службе RESTful, используя https. Также меня немного раздражали все ответы, которые предлагали вообще отключить проверку сертификатов. Если вы это сделаете, какой смысл https?

После гугле на эту тему на некоторое время, я , наконец , нашел это решение , в котором внешние банки не нужны, только для Android API. Спасибо Эндрю Смиту, который разместил его в июле 2014 года

 /**
 * Set up a connection to myservice.domain using HTTPS. An entire function
 * is needed to do this because myservice.domain has a self-signed certificate.
 * 
 * The caller of the function would do something like:
 * HttpsURLConnection urlConnection = setUpHttpsConnection("https://littlesvr.ca");
 * InputStream in = urlConnection.getInputStream();
 * And read from that "in" as usual in Java
 * 
 * Based on code from:
 * https://developer.android.com/training/articles/security-ssl.html#SelfSigned
 */
public static HttpsURLConnection setUpHttpsConnection(String urlString)
{
    try
    {
        // Load CAs from an InputStream
        // (could be from a resource or ByteArrayInputStream or ...)
        CertificateFactory cf = CertificateFactory.getInstance("X.509");

        // My CRT file that I put in the assets folder
        // I got this file by following these steps:
        // * Go to https://littlesvr.ca using Firefox
        // * Click the padlock/More/Security/View Certificate/Details/Export
        // * Saved the file as littlesvr.crt (type X.509 Certificate (PEM))
        // The MainActivity.context is declared as:
        // public static Context context;
        // And initialized in MainActivity.onCreate() as:
        // MainActivity.context = getApplicationContext();
        InputStream caInput = new BufferedInputStream(MainActivity.context.getAssets().open("littlesvr.crt"));
        Certificate ca = cf.generateCertificate(caInput);
        System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());

        // Create a KeyStore containing our trusted CAs
        String keyStoreType = KeyStore.getDefaultType();
        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);

        // Create a TrustManager that trusts the CAs in our KeyStore
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);

        // Create an SSLContext that uses our TrustManager
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, tmf.getTrustManagers(), null);

        // Tell the URLConnection to use a SocketFactory from our SSLContext
        URL url = new URL(urlString);
        HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection();
        urlConnection.setSSLSocketFactory(context.getSocketFactory());

        return urlConnection;
    }
    catch (Exception ex)
    {
        Log.e(TAG, "Failed to establish SSL connection to server: " + ex.toString());
        return null;
    }
}

Это хорошо сработало для моего приложения-макета.

Гонсало Фернандес
источник
X509Сертификат, какой я должен импортировать Java или Javax?
Сиддхарт
Я импортировалimport java.security.cert.X509Certificate;
Гонсало Фернандес
Спасибо за это. Это действительно работа и просто
Anuradhe Dilshan
6

Лучший ответ не сработал для меня. После некоторого расследования я нашел необходимую информацию о «Android Developer»: https://developer.android.com/training/articles/security-ssl.html#SelfSigned

Создание пустой реализации X509TrustManager сделало свое дело:

private static class MyTrustManager implements X509TrustManager
{

    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType)
         throws CertificateException
    {
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType)
        throws CertificateException
    {
    }

    @Override
    public X509Certificate[] getAcceptedIssuers()
    {
        return null;
    }

}

...

HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
try
{
    // Create an SSLContext that uses our TrustManager
    SSLContext context = SSLContext.getInstance("TLS");
    TrustManager[] tmlist = {new MyTrustManager()};
    context.init(null, tmlist, null);
    conn.setSSLSocketFactory(context.getSocketFactory());
}
catch (NoSuchAlgorithmException e)
{
    throw new IOException(e);
} catch (KeyManagementException e)
{
    throw new IOException(e);
}
conn.setRequestMethod("GET");
int rcode = conn.getResponseCode();

Помните, что эта пустая реализация TustManager является лишь примером, и ее использование в продуктивной среде может создать серьезную угрозу безопасности!

Маркус Ленгер
источник
1
просто fyi - idk, если это было так в то время, но они, кажется, решительно не одобряют этот подход сейчас (см. примечание)
Saik Caskey
6

Google рекомендует использовать Android Volley для соединений HTTP / HTTPS , поскольку это HttpClientустарело. Итак, вы знаете правильный выбор :).

А также, НИКОГДА NUKE SSL-сертификаты (НИКОГДА !!!).

Использование ядерных сертификатов SSL полностью противоречит цели SSL, которая способствует безопасности . Нет смысла использовать SSL, если вы планируете бомбить все SSL-сертификаты. Лучшим решением было бы, если бы не использование SSL, или лучшим решением было бы созданиеTrustManager в вашем приложении + с использованием Android Volley для соединений HTTP / HTTPS.

Вот Gist, который я создал с помощью обычного LoginApp, выполняющего HTTPS-соединения с использованием самоподписанного сертификата на стороне сервера, принятого в приложении.

Вот еще один Gist, который может помочь для создания самоподписанных сертификатов SSL для настройки на вашем сервере, а также для использования сертификата в вашем приложении. Очень важно: вы должны скопировать файл .crt, сгенерированный приведенным выше сценарием, в каталог «raw» из вашего проекта Android.

ivanleoncz
источник
Здравствуйте, Иван, я никогда не работал с SSL-сертификатами. Не могли бы вы уточнить немного, как мне получить файл .crt?
jlively
Привет, Джайвли! Понимаю. Ну конечно; естественно. Но сначала, не могли бы вы взглянуть на второй Gist, который я упомянул выше? Я поместил два файла в этот список: один - файл, используемый сценарием, а другой - сам сценарий, который использует двоичный файл «openssl» для чтения файла, а затем создает файл, содержащий сертификат SSL ( .crt). Дайте мне знать, если вам удалось понять все это. С уважением :).
Иванлеонч
Хм, да, я посмотрел на эти 2 гист, но я не могу понять, как их использовать?
Jlively
4

Вот как вы можете добавить дополнительные сертификаты в хранилище ключей, чтобы избежать этой проблемы: Доверие всем сертификатам с использованием HttpClient через HTTPS

Он не будет запрашивать пользователя, как вы спрашиваете, но уменьшит вероятность того, что пользователь столкнется с ошибкой «Сертификат недоверенного сервера».

emmby
источник
Только для целей тестирования, вы не можете опубликовать приложение в Play Store , этот трюк , потому что она будет отклонена
Ariel
3

Самый простой способ создания SSL-сертификата

Откройте Firefox (я полагаю, это также возможно с Chrome, но мне легче с FF)

Посетите ваш сайт разработки с самозаверяющим сертификатом SSL.

Нажмите на сертификат (рядом с названием сайта)

Нажмите на «Больше информации»

Нажмите на «Просмотреть сертификат»

Нажмите на «Детали»

Нажмите на «Экспорт ...»

Выберите «Сертификат X.509 с цепочкой (PEM)», выберите папку и имя, чтобы сохранить его, и нажмите «Сохранить».

Перейдите в командную строку, в каталог, в который вы скачали pem-файл, и выполните «openssl x509 -inform PEM -outform DM -in .pem -out .crt»

Скопируйте файл .crt в корень папки / sdcard на устройстве Android. Внутри устройства Android выберите Настройки> Безопасность> Установить из хранилища.

Он должен обнаружить сертификат и позволить вам добавить его на устройство. Найдите свой сайт разработки.

В первый раз он должен попросить вас подтвердить исключение безопасности. Вот и все.

Сертификат должен работать с любым браузером, установленным на вашем Android (Браузер, Chrome, Opera, Dolphin ...)

Помните, что если вы обслуживаете ваши статические файлы из другого домена (мы все суки скорости страницы), вам также необходимо добавить сертификат для этого домена.

Мани Кандан
источник
2

Я написал небольшую библиотеку ssl-utils-android, чтобы доверять определенному сертификату на Android.

Вы можете просто загрузить любой сертификат, указав имя файла из каталога активов.

Использование:

OkHttpClient client = new OkHttpClient();
SSLContext sslContext = SslUtils.getSslContextForCertificateFile(context, "BPClass2RootCA-sha2.cer");
client.setSslSocketFactory(sslContext.getSocketFactory());
Klimat
источник
1

Ни одно из этих исправлений не помогло моей платформе разработки, ориентированной на SDK 16, выпуск 4.1.2, поэтому я нашел обходной путь.

Мое приложение хранит данные на сервере, используя " http://www.example.com/page.php?data=somedata "

Недавно page.php был перемещен в « https://www.secure-example.com/page.php », и я продолжаю получать сообщение «javax.net.ssl.SSLException: сертификат недоверенного сервера».

Вместо того, чтобы принимать все сертификаты только для одной страницы, начиная с этого руководства, я решил свою проблему, написав свой собственный page.php, опубликованный на « http://www.example.com/page.php ».

<?php

caronte ("https://www.secure-example.com/page.php");

function caronte($url) {
    // build curl request
    $ch = curl_init();
    foreach ($_POST as $a => $b) {
        $post[htmlentities($a)]=htmlentities($b);
    }
    curl_setopt($ch, CURLOPT_URL,$url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS,http_build_query($post));

    // receive server response ...
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $server_output = curl_exec ($ch);
    curl_close ($ch);

    echo $server_output;
}

?>
Rudy
источник
1

19 января 2020 г. Самозаверяющий сертификат ВЫПУСК FIX:

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

КОТЛИН КОД

  private fun disableSSLCertificateChecking() {
        val hostnameVerifier = object: HostnameVerifier {
            override fun verify(s:String, sslSession: SSLSession):Boolean {
                return true
            }
        }
        val trustAllCerts = arrayOf<TrustManager>(object: X509TrustManager {
            override fun getAcceptedIssuers(): Array<X509Certificate> {
                TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
            }

            //val acceptedIssuers:Array<X509Certificate> = null
            @Throws(CertificateException::class)
            override fun checkClientTrusted(arg0:Array<X509Certificate>, arg1:String) {// Not implemented
            }
            @Throws(CertificateException::class)
            override fun checkServerTrusted(arg0:Array<X509Certificate>, arg1:String) {// Not implemented
            }
        })
        try
        {
            val sc = SSLContext.getInstance("TLS")
            sc.init(null, trustAllCerts, java.security.SecureRandom())
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory())
            HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier)
        }
        catch (e: KeyManagementException) {
            e.printStackTrace()
        }
        catch (e: NoSuchAlgorithmException) {
            e.printStackTrace()
        }
    }
Шобхакар Тивари
источник
0

Может быть, это будет полезно ... это работает на клиентах Java, использующих самозаверяющие сертификаты (проверка сертификата не производится). Будьте осторожны и используйте его только для разработки, потому что это совсем не безопасно !!

Как игнорировать ошибки SSL-сертификата в Apache HttpClient 4.0

Надеюсь, это будет работать на Android, просто добавив библиотеку HttpClient ... удачи!

эй
источник
1
Нет, он не работает на Android, так как полагается на устаревшие методы, которых нет в варианте Android :-(
kellyfj
0

Эта проблема возникает из-за отсутствия поддержки SNI (Server Name Identification) в A, ndroid 2.x. Я боролся с этой проблемой в течение недели, пока не наткнулся на следующий вопрос, который не только дает хорошее представление о проблеме, но также обеспечивает рабочее и эффективное решение без каких-либо пробелов в безопасности.

Ошибка «Нет сертификата пера» в Android 2.3, но НЕ в 4

Alumat
источник