прийняття HTTPS-з'єднань із самопідписаними сертифікатами


153

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

Я бачив рішення, де ви просто приймаєте всі сертифікати, але що робити, якщо я хочу запитати користувача?

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


Це прийняте рішення працювало на me- stackoverflow.com/questions/2642777/…
Venkatesh

Відповіді:


171

Перше, що вам потрібно зробити - це встановити рівень перевірки. Таких рівнів не так багато:

  • ALLOW_ALL_HOSTNAME_VERIFIER
  • BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
  • STRICT_HOSTNAME_VERIFIER

Хоча метод setHostnameVerifier () застарілий для нового бібліотечного апаша, але для версії в 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
Ферма

124

Наступні основні кроки необхідні для досягнення захищеного з'єднання з боку сертифікаційних органів, які не вважаються довіреними платформою Android.

За запитом багатьох користувачів, я відобразив тут найважливіші частини моєї статті блогу :

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

Візьміть серти

Ви повинні отримати всі сертифікати, які будують ланцюжок від сертифікату кінцевої точки, аж до Root CA. Це означає, що будь-які (якщо вони є) проміжні сертифікати CA, а також корінь CA. Вам не потрібно отримувати сертифікат кінцевої точки.

Створіть магазин брелоків

Завантажте постачальник BouncyCastle і зберігайте його у відомому місці. Також переконайтеся, що ви можете викликати команду keytool (зазвичай розташована під папкою bin вашої установки JRE).

Тепер імпортуйте отримані серти (не імпортуйте кінцівок кінцевих точок) у форматну клавішу BouncyCastle.

Я цього не перевіряв, але думаю, що порядок імпорту сертифікатів є важливим. Це означає, що імпортуйте спочатку найнижчий проміжний сертифікат CA, а потім аж до сертифіката Root CA.

За допомогою наступної команди буде створено нову сховище ключів (якщо її ще немає) з паролем mysecret і імпортуватиме проміжний сертифікат CA. Я також визначив постачальника 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
Це корисно лише для отримання сертифікатів перед відправкою вашої заявки. Насправді не допомагає користувачам приймати власні сертифікати. для вашої заявки
Нечіткий

Привіт усім, хтось може сказати мені процес перевірки для зберігання брелоків з довіреною ланкою для вищезазначеної реалізації ??? заздалегідь дякую ..
andriod_testing

Це спрацювало нормально. Але зараз я стикаюся з проблемою, коли переробляти сертифікат на сервері. Як не дивно, що кожного разу, коли я оновлюю сертифікат на своєму сервері, магазин клієнта також повинен бути оновлений. Має бути кращий спосіб: |
bpn

Відповідь 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


Де я можу отримати .crtфайли? Завантажити з сервера?
zionpi

@zionpi Файл сертифіката буде тим самим, який використовує сервер із підтримкою TLS, до якого ви підключаєтесь.
SD

Дякую! Це було так просто!
kapil thadani

@SD Як я можу використовувати файл .P12 замість .crt?
R Nair

Я такий же сумніву холодно ви допомогти stackoverflow.com/questions/57389622 / ...
StezPet

8

Мене було розчаровано намагатися підключити додаток Android до мого RESTful сервісу за допомогою https. Також мене трохи роздратували всі відповіді, які пропонували взагалі відключити перевірку сертифікатів. Якщо ви так зробите, у чому сенс https?

На деякий час гуглившись над цією темою, я нарешті знайшов це рішення там, де зовнішні банки не потрібні, лише API-програми Android. Дякуємо Ендрю Сміту, який опублікував це в липні 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;
Гонсало Фернандес

Дякую за це. Це дійсно працює і просто
Анурадхе Ділшан

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 з'єднання, з допомогою самоподпісанного сертифіката на стороні сервера, прийнятий на App.

Ось також ще одна історія, яка може допомогти для створення самопідписаних сертифікатів SSL для налаштування на вашому сервері, а також використання сертифіката у вашому додатку. Дуже важливо: ви повинні скопіювати .crt файл, який був створений вищевказаним сценарієм, у каталог "raw" з вашого проекту Android.


Привіт Іване, я ніколи не працював із сертифікатами SSL. Чи хотіли б ви трохи розібратися, як мені отримати файл .crt?
jlively

Привіт Jively! Я бачу. Так, звісно. Але по-перше, ви б проти зазирнути до другої суті, про яку я згадував вище? Я помістив два файли на цей Gist: один - це файл, який використовується сценарієм, а другий - це сам сценарій, який використовує двійковий код "openssl" для того, щоб прочитати файл, а потім, створивши файл, який містить сертифікат SSL ( .crt). Дайте мені знати, чи вам вдалося зрозуміти всю справу. З повагою :).
ivanleoncz

Хм так, я переглянув ці 2 суті, але я не можу зрозуміти, як я їх використовую?
jlively

4

Ось як можна додати додаткові сертифікати до KeyStore, щоб уникнути цієї проблеми: Довіряючи всім сертифікатам за допомогою HttpClient через HTTPS

Він не підкаже користувачеві, як ви запитуєте, але зробить меншою ймовірність, що користувач потрапить у помилку "Не довірений сертифікат сервера".


Лише для тестування ви не можете публікувати додаток у Play Store із цим фокусом, оскільки його буде відхилено
аріель

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, дельфін ...)

Пам’ятайте, що якщо ви подаєте статичні файли з іншого домену (ми всі суки швидкості сторінки), вам також потрібно додати сертифікат для цього домену.


2

Я написав невелику бібліотеку ssl-utils-android щоб довірити певний сертифікат на Android.

Ви можете просто завантажити будь-який сертифікат, вказавши ім'я файлу з каталогу активів.

Використання:

OkHttpClient client = new OkHttpClient();
SSLContext sslContext = SslUtils.getSslContextForCertificateFile(context, "BPClass2RootCA-sha2.cer");
client.setSslSocketFactory(sslContext.getSocketFactory());

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: Не довірений сертифікат сервера".

Замість прийняття всіх сертифікатів лише для однієї сторінки, починаючи з цього посібника, я вирішив свою проблему, написавши власну сторінку.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;
}

?>

1

19 січня 2020 року Самостійно підписаний сертифікат ВИПУСК:

Для відтворення відео, зображень, виклику веб-сервісу для будь-якого самопідписаного сертифіката або підключення до будь-якої незахищеної 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 (ідентифікація імені сервера) вA, ndroid 2.x. Я боровся з цією проблемою тиждень, поки не зіткнувся з таким питанням, яке не тільки дає хорошу основу проблеми, але й забезпечує ефективне та ефективне рішення, позбавлене будь-яких дір у безпеці.

Помилка "немає сертифікату рівних" в Android 2.3, але НЕ в 4

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.