60
задан 24 February 2016 в 10:09

2 ответа

Я знаю, что это сообщение довольно старо, bui я хочу совместно использовать решение, которое работало на меня с последним обновлением OkHttp, 3.12.1 версия во время, которое я пишу.

, В первую очередь, необходимо получить объект KeyStore, который будет затем добавлен к TrustManager:

/**
 *  @param context The Android context to be used for retrieving the keystore from raw resource
 * @return the KeyStore read or null on error
 */
private static KeyStore readKeyStore(Context context) {

    char[] password = "keystore_password".toCharArray();

    // for non-android usage:
    // try(FileInputStream is = new FileInputStream(keystoreName)) {

    try(InputStream is = context.getResources().openRawResource(R.raw.keystore)) {
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(is, password);
        return ks;
    } catch (CertificateException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    }

    return null;
}

Теперь можно получить сборку OkHttpClient с самоподписанным сертификатом в keystore:

/**
 * @param context The Android context used to obtain the KeyStore
 * @return the builded OkHttpClient or null on error
 */
public static OkHttpClient getOkHttpClient(Context context) {

    try {
        TrustManagerFactory trustManagerFactory = TrustManagerFactory
                .getInstance(TrustManagerFactory.getDefaultAlgorithm());

        trustManagerFactory.init(readKeyStore(context));

        X509TrustManager trustManager = (X509TrustManager) trustManagerFactory.getTrustManagers()[0];
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, new TrustManager[]{trustManager}, null);

        return new OkHttpClient.Builder()
                .hostnameVerifier((hostname, session) -> {
                    HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
                    /* Never return true without verifying the hostname, otherwise you will be vulnerable
                    to man in the middle attacks. */
                    return  hv.verify("your_hostname_here", session);
                })
                .sslSocketFactory(sslContext.getSocketFactory(), trustManager)
                .build();

    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    } catch (KeyManagementException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }

    return null;
}

Помнят, что этому высоко препятствуют для возврата всегда верный в hostnameVerifier для предотвращения риска человека в средних нападениях.

0
ответ дан 1 November 2019 в 10:35

У меня была та же проблема, и я зафиксировал ее с клиент okhttp следующим образом:

1.) Добавляют certificate файл к src/main/res/raw/, который включает это содержание:

-----BEGIN CERTIFICATE-----
...=
-----END CERTIFICATE-----

2.) Instanciate okHttpClient:

OkHttpClient client = new OkHttpClient.Builder()
                .sslSocketFactory(getSslContext(context).getSocketFactory())
                .build();

3.) Вот используемый getSslContext(Context context) метод:

SSLContext getSslContext(Context context) throws Exception {
    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); // "BKS"
    ks.load(null, null);

    InputStream is = context.getResources().openRawResource(R.raw.certificate);
    String certificate = Converter.convertStreamToString(is);

    // generate input stream for certificate factory
    InputStream stream = IOUtils.toInputStream(certificate);

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

    ks.setCertificateEntry("av-ca", ca);

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

    // Create a SSLContext with the certificate that uses tmf (TrustManager)
    sslContext = SSLContext.getInstance("TLS");
    sslContext.init(null, tmf.getTrustManagers(), new SecureRandom());

    return sslContext;
}

, Если существует потребность добавить несколько сертификатов SslContext, здесь , решение.

0
ответ дан 1 November 2019 в 10:35

Другие вопросы по тегам:

Похожие вопросы: