menerima koneksi HTTPS dengan sertifikat yang ditandatangani sendiri

153

Saya mencoba membuat koneksi HTTPS, menggunakan HttpClientlib, tetapi masalahnya adalah, karena sertifikat tersebut tidak ditandatangani oleh Otoritas Sertifikat (CA) yang diakui seperti Verisign , GlobalSIgn , dll., Yang tercantum pada set Sertifikat Tepercaya Android, Saya terus mendapatkan javax.net.ssl.SSLException: Not trusted server certificate.

Saya telah melihat solusi di mana Anda cukup menerima semua sertifikat, tetapi bagaimana jika saya ingin bertanya kepada pengguna?

Saya ingin mendapatkan dialog yang mirip dengan browser, membiarkan pengguna memutuskan untuk melanjutkan atau tidak. Lebih disukai saya ingin menggunakan sertifikat yang sama seperti browser. Ada ide?

Morten
sumber
Solusi yang diterima ini berfungsi untuk me- stackoverflow.com/questions/2642777/…
Venkatesh

Jawaban:

171

Hal pertama yang perlu Anda lakukan adalah mengatur tingkat verifikasi. Level seperti itu tidak terlalu banyak:

  • ALLOW_ALL_HOSTNAME_VERIFIER
  • BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
  • STRICT_HOSTNAME_VERIFIER

Meskipun metode setHostnameVerifier () sudah usang untuk apache perpustakaan baru, tetapi untuk versi di Android SDK adalah normal. Jadi kami mengambil ALLOW_ALL_HOSTNAME_VERIFIERdan mengaturnya di pabrik metode SSLSocketFactory.setHostnameVerifier().

Selanjutnya, Anda perlu mengatur pabrik kami untuk protokol ke https. Untuk melakukan ini, cukup panggil SchemeRegistry.register()metode tersebut.

Maka Anda perlu membuat DefaultHttpClientdengan SingleClientConnManager. Juga dalam kode di bawah ini Anda dapat melihat bahwa secara default juga akan menggunakan flag kami ( ALLOW_ALL_HOSTNAME_VERIFIER) oleh metodeHttpsURLConnection.setDefaultHostnameVerifier()

Kode di bawah ini berfungsi untuk saya:

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);
Nikolay Moskvin
sumber
6
Sayangnya saya tidak dapat membuat kode ini berfungsi, saya masih mendapatkan "Sertifikat server tidak tepercaya". Apakah ada izin tambahan yang harus saya set untuk membuatnya berfungsi?
Juriy
1
Bukankah kode ini hanya menerima semua sertifikat? Saya perlu munculan untuk menerimanya.
Morten
3
Saya menggunakan org.apache.http.conn.ssl.SSLSocketFactorymengapa saya ingin menggunakan javax.net.ssl.HttpsURLConnection??
Seseorang di suatu tempat
9
Bisakah Anda menjelaskan bagaimana kode ini lebih baik daripada menonaktifkan verifikasi sertifikat sepenuhnya? Saya tidak terbiasa dengan ssl API android, tetapi sekilas ini tampaknya sama sekali tidak aman terhadap penyerang aktif.
CodesInChaos
3
Saya akan menyarankan menggunakan ThreadSafeClientConnManager daripada SingleClientConnManager
Pertanian
124

Langkah-langkah utama berikut ini diperlukan untuk mencapai koneksi aman dari Otoritas Sertifikasi yang tidak dianggap dipercaya oleh platform android.

Seperti yang diminta oleh banyak pengguna, saya telah mencerminkan bagian terpenting dari artikel blog saya di sini:

  1. Raih semua sertifikat yang diperlukan (root dan CA perantara)
  2. Buat keystore dengan keytool dan penyedia BouncyCastle dan impor sertifikat
  3. Muat keystore di aplikasi Android Anda dan gunakan untuk koneksi yang aman (saya sarankan untuk menggunakan Apache HttpClient alih-alih standar java.net.ssl.HttpsURLConnection(lebih mudah dimengerti, lebih banyak performan)

Raih sertifikat tersebut

Anda harus mendapatkan semua sertifikat yang membangun rantai dari sertifikat titik akhir hingga Root CA. Ini berarti, setiap (jika ada) CA CA menengah dan juga CA CA Root. Anda tidak perlu mendapatkan sertifikat titik akhir.

Buat keystore

Unduh Penyedia BouncyCastle dan simpan ke lokasi yang diketahui. Juga pastikan bahwa Anda dapat menjalankan perintah keytool (biasanya terletak di bawah folder bin instalasi JRE Anda).

Sekarang impor sertifikat yang diperoleh (jangan impor sertifikat titik akhir) ke dalam keystore yang diformat BouncyCastle.

Saya tidak mengujinya, tetapi saya pikir urutan mengimpor sertifikat itu penting. Ini berarti, impor sertifikat CA Menengah paling bawah terlebih dahulu dan kemudian sampai ke sertifikat CA Root.

Dengan perintah berikut, keystore baru (jika belum ada) dengan kata sandi mysecret akan dibuat dan sertifikat CA Menengah akan diimpor. Saya juga mendefinisikan penyedia BouncyCastle, di mana dapat ditemukan pada sistem file saya dan format keystore. Jalankan perintah ini untuk setiap sertifikat dalam rantai.

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

Verifikasi apakah sertifikat diimpor dengan benar ke dalam keystore:

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

Haruskah mengeluarkan seluruh rantai:

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

Sekarang Anda dapat menyalin keystore sebagai sumber daya mentah di aplikasi Android Anda di bawah res/raw/

Gunakan keystore di aplikasi Anda

Pertama-tama kita harus membuat Apache HttpClient kustom yang menggunakan keystore kita untuk koneksi 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);
        }
    }
}

Kami telah membuat HttpClient kustom kami, sekarang kami dapat menggunakannya untuk koneksi yang aman. Misalnya ketika kami melakukan panggilan GET ke sumber daya 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();

Itu dia ;)

saxos
sumber
8
Ini hanya berguna untuk mendapatkan sertifikat sebelum mengirim aplikasi Anda. Tidak benar-benar membantu pengguna menerima sertifikat mereka sendiri. untuk aplikasi Anda
Fuzzy
Hai semua dapatkah seseorang memberitahu saya proses validasi untuk keystore dengan truststore untuk implementasi di atas ??? terima kasih sebelumnya ..
andriod_testing
Ini bekerja dengan baik..tapi sekarang saya menghadapi masalah ketika saya merekam kembali sertifikat di server. Tampaknya aneh bahwa setiap kali saya memperbarui sertifikat di server saya, toko sisi klien juga harus diperbarui. Harus ada cara yang lebih baik: |
bpn
Gr8 menjawab, saya akan menyarankan menggunakan ThreadSafeClientConnManager daripada SingleClientConnManager
Pertanian
Saya telah menambahkan /res/raw/mykeystore.bks, meskipun tidak dapat menyelesaikan referensi untuk itu. bagaimana mengatasi ini?
uniruddh
16

Jika Anda memiliki sertifikat khusus yang ditandatangani sendiri di server yang tidak ada di perangkat, Anda dapat menggunakan kelas di bawah ini untuk memuatnya dan menggunakannya di sisi klien di Android:

Tempatkan *.crtfile sertifikat /res/rawsehingga tersedia dariR.raw.*

Gunakan kelas di bawah ini untuk mendapatkan HTTPClientatau HttpsURLConnectionyang akan memiliki pabrik soket menggunakan sertifikat itu:

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;
    }

}

Poin-poin penting:

  1. Certificateobjek dihasilkan dari .crtfile.
  2. Default KeyStoredibuat.
  3. keyStore.setCertificateEntry("ca", cert)menambahkan sertifikat ke penyimpanan kunci di bawah alias "ca". Anda memodifikasi kode untuk menambahkan lebih banyak sertifikat (CA menengah dll).
  4. Tujuan utama adalah untuk menghasilkan SSLSocketFactoryyang kemudian dapat digunakan oleh HTTPClientatau HttpsURLConnection.
  5. SSLSocketFactory dapat dikonfigurasi lebih lanjut, misalnya untuk melewati verifikasi nama host, dll.

Informasi lebih lanjut di: http://developer.android.com/training/articles/security-ssl.html

SD
sumber
Di mana saya bisa mendapatkan .crtfile? Unduh dari server?
zionpi
@zionpi File sertifikat akan sama dengan yang digunakan oleh server berkemampuan TLS yang Anda sambungkan.
SD
Terima kasih! Ini sangat mudah!
kapil thadani
@ SD Bagaimana saya bisa menggunakan file .P12 alih-alih .crt?
Rakesh R Nair
Saya memiliki keraguan yang sama dingin, tolong bantu stackoverflow.com/questions/57389622/…
StezPet
8

Saya frustrasi mencoba menghubungkan Aplikasi Android saya ke layanan RESTful saya menggunakan https. Saya juga agak jengkel tentang semua jawaban yang menyarankan untuk menonaktifkan memeriksa sertifikat sama sekali. Jika Anda melakukannya, apa gunanya https?

Setelah googled tentang topik untuk sementara waktu, saya akhirnya menemukan solusi ini di mana guci eksternal tidak diperlukan, hanya Android API. Terima kasih kepada Andrew Smith, yang mempostingnya pada Juli, 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;
    }
}

Ini bekerja dengan baik untuk App mockup saya.

Gonzalo Fernández
sumber
Sertifikat X509 mana yang harus saya impor java atau javax?
Siddharth
Saya mengimporimport java.security.cert.X509Certificate;
Gonzalo Fernández
Terima kasih untuk ini. Ini benar-benar bekerja dan sederhana
Anuradhe Dilshan
6

Jawaban teratas tidak berhasil untuk saya. Setelah beberapa penyelidikan saya menemukan informasi yang diperlukan pada "Pengembang Android": https://developer.android.com/training/articles/security-ssl.html#SelfSigned

Membuat implementasi X509TrustManager yang kosong melakukan trik:

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();

Ketahuilah bahwa penerapan TustManager yang kosong ini hanyalah contoh dan menggunakannya di lingkungan yang produktif akan menyebabkan ancaman keamanan yang parah!

Markus Lenger
sumber
1
hanya fyi - idk jika sudah seperti ini pada waktu itu, tetapi mereka tampaknya sangat tidak mendukung pendekatan ini sekarang (lihat catatan)
Saik Caskey
6

Google merekomendasikan penggunaan Android Volley untuk koneksi HTTP / HTTPS , karena HttpClientsudah tidak digunakan lagi. Jadi, Anda tahu pilihan yang tepat :).

Dan juga, TIDAK PERNAH NUKE SSL Certificate (TIDAK PERNAH !!!).

Untuk membatalkan Sertifikat SSL, sama sekali bertentangan dengan tujuan SSL, yang mempromosikan keamanan . Tidak ada gunanya menggunakan SSL, jika Anda berencana untuk mengebom semua sertifikat SSL yang datang. Solusi yang lebih baik adalah, tidak menggunakan SSL, atau solusi yang lebih baik, akan membuat custom TrustManagerdi App + Anda menggunakan Android Volley untuk koneksi HTTP / HTTPS.

Berikut adalah Intisari yang saya buat, dengan LoginApp dasar, melakukan koneksi HTTPS, menggunakan Sertifikat yang Ditandatangani Sendiri di sisi server, diterima di App.

Berikut juga Intisari lain yang dapat membantu, untuk membuat Sertifikat SSL yang Ditandatangani Sendiri untuk pengaturan di Server Anda dan juga menggunakan sertifikat pada Aplikasi Anda. Sangat penting: Anda harus menyalin file .crt yang dihasilkan oleh skrip di atas, ke direktori "mentah" dari proyek Android Anda.

ivanleoncz
sumber
Halo Ivan, saya belum pernah bekerja dengan sertifikat SSL. Apakah Anda ingin sedikit menguraikan, bagaimana cara mendapatkan file .crt?
gembira
Hai Jively! Saya melihat. Ya tentu saja. Tapi pertama-tama, maukah Anda melihat pada intisari kedua yang saya sebutkan di atas? Saya menaruh dua file pada Gist ini: satu adalah file yang digunakan oleh skrip dan yang lainnya, adalah skrip itu sendiri, yang menggunakan biner "openssl" untuk membaca file dan kemudian, membangun file yang berisi Sertifikat SSL ( .crt). Beri tahu saya jika Anda berhasil memahami semuanya. Salam :).
ivanleoncz
Hmm ya saya telah melihat 2 inti itu, tapi saya tidak bisa mengerti bagaimana cara menggunakannya?
singkat
4

Inilah cara Anda dapat menambahkan sertifikat tambahan ke KeyStore Anda untuk menghindari masalah ini: Mempercayai semua sertifikat menggunakan HttpClient melalui HTTPS

Itu tidak akan meminta pengguna seperti yang Anda minta, tetapi itu akan membuat lebih kecil kemungkinannya bahwa pengguna akan mengalami kesalahan "Sertifikat server tidak tepercaya".

emmby
sumber
Hanya untuk tujuan pengujian, Anda tidak dapat menerbitkan aplikasi di Play Store dengan trik ini karena itu akan ditolak
ariel
3

Cara termudah untuk membuat sertifikat SSL

Buka Firefox (saya kira itu juga mungkin dengan Chrome, tetapi lebih mudah bagi saya dengan FF)

Kunjungi situs pengembangan Anda dengan sertifikat SSL yang ditandatangani sendiri.

Klik pada sertifikat (di sebelah nama situs)

Klik pada "Informasi lebih lanjut"

Klik pada "Lihat sertifikat"

Klik pada "Detail"

Klik pada "Ekspor ..."

Pilih "X.509 Certificate whith chain (PEM)", pilih folder dan nama untuk menyimpannya dan klik "Simpan"

Pergi ke baris perintah, ke direktori tempat Anda mengunduh file pem dan jalankan "openssl x509-informasikan PEM-outform DM-in .pem -out .crt"

Salin file .crt ke root folder / sdcard di dalam perangkat Android Anda Di dalam perangkat Android Anda, Pengaturan> Keamanan> Instal dari penyimpanan.

Ini harus mendeteksi sertifikat dan membiarkan Anda menambahkannya ke perangkat Browse ke situs pengembangan Anda.

Pertama kali itu harus meminta Anda untuk mengkonfirmasi pengecualian keamanan. Itu saja.

Sertifikat harus bekerja dengan browser apa pun yang diinstal di Android Anda (Browser, Chrome, Opera, Dolphin ...)

Ingat bahwa jika Anda menyajikan file statis dari domain lain (kami semua adalah pelacur kecepatan halaman), Anda juga perlu menambahkan sertifikat untuk domain itu.

Mani kandan
sumber
2

Saya menulis perpustakaan kecil ssl-utils-android untuk mempercayai sertifikat tertentu di Android.

Anda cukup memuat sertifikat apa pun dengan memberikan nama file dari direktori aset.

Pemakaian:

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

Tidak satu pun dari perbaikan ini yang berfungsi untuk platform saya yang menargetkan SDK 16, Rilis 4.1.2, jadi saya menemukan solusinya.

Aplikasi saya menyimpan data di server menggunakan " http://www.example.com/page.php?data=somedata "

Baru-baru ini page.php dipindahkan ke " https://www.secure-example.com/page.php " dan saya terus mendapatkan "javax.net.ssl.SSLException: Sertifikat server tidak tepercaya".

Alih-alih menerima semua sertifikat hanya untuk satu halaman, mulai dengan panduan ini saya memecahkan masalah saya menulis page.php saya sendiri yang diterbitkan di " 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
sumber
1

19 Jan, 2020 Sertifikat Mandiri, MASALAH TETAP:

Untuk memutar video, gambar, memanggil layanan web untuk sertifikat yang ditandatangani sendiri atau menghubungkan ke url tanpa jaminan, panggil saja metode ini sebelum melakukan tindakan apa pun, itu akan memperbaiki masalah Anda mengenai masalah sertifikat:

KODE KOTLIN

  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()
        }
    }
Shobhakar Tiwari
sumber
0

Mungkin ini akan membantu ... ini berfungsi pada klien java menggunakan sertifikat yang ditandatangani sendiri (tidak ada pemeriksaan sertifikat). Hati-hati dan gunakan hanya untuk kasus pengembangan karena itu sama sekali tidak aman !!

Cara mengabaikan kesalahan sertifikat SSL di Apache HttpClient 4.0

Semoga berhasil di Android dengan hanya menambahkan pustaka HttpClient ... semoga berhasil !!

EmP
sumber
1
Tidak itu tidak berfungsi di android karena bergantung pada metode yang sudah tidak digunakan yang tidak ada dalam varian Android :-(
kellyfj
0

Ini adalah masalah yang disebabkan oleh kurangnya dukungan SNI (Server Name Identification) diA, ndroid 2.x. Saya berjuang dengan masalah ini selama seminggu sampai saya menemukan pertanyaan berikut, yang tidak hanya memberikan latar belakang masalah yang baik tetapi juga memberikan solusi yang efektif dan bekerja tanpa ada celah keamanan.

Kesalahan 'Tidak ada sertifikat sebaya' di Android 2.3 tetapi TIDAK di 4

alumat
sumber