Menghubungkan ke Server Parse di VPS menggunakan https (sertifikat self-sined untuk SSL)

Untuk beberapa alasan, pengguna Parse harus memigrasikan lingkungan Parse mereka ke VPS (ini adalah kasus pertanyaan saya) atau Heroku, AWS (tidak memerlukan platform ini), dll. Ada Parse SDK baru untuk Android (1.13.0) yang memungkinkan untuk menginisialisasi koneksi menggunakan antarmuka Parse baru, sebagai berikut:

Parse.initialize(new Parse.Configuration.Builder(this)
                .applicationId("myAppId")
                .clientKey(null) 
                .addNetworkInterceptor(new ParseLogInterceptor())
                .server("https://VPS_STATIC_IP_ADDRESS/parse/").build());

Permintaan semacam ini dilakukan menggunakan port 443. File konektor .js (nodejs) yang sesuai telah diedit sehingga port 443 terhubung secara lokal ke port 1337 (port-listener) dan berfungsi saat mengakses Parse Server di browser (jarak jauh, tentu saja: dari luar VPS) yang memungkinkan untuk menerapkan sertifikat yang ditandatangani sendiri dan melangkah lebih jauh. Tapi ketika aplikasi Android (peluncur) mencoba menghubungkannya, aplikasi itu tidak bisa karena sertifikat yang ditandatangani sendiri. Apakah ada kemungkinan dari dalam Parse SDK untuk menerapkan sertifikat yang ditandatangani sendiri?

P.S. Apakah benar ada bug terkait masalah ini dan inilah alasan mengapa versi Parse 1.13.1 dirilis? Jika ya, di mana saya bisa mendapatkan perpustakaan jar versi ini?

Terima kasih!


person LowLevel    schedule 18.06.2016    source sumber
comment
Anda mungkin harus memperbaiki kesalahan ketik pada judul...   -  person Croc    schedule 12.07.2016


Jawaban (1)


Saya baru saja menyelesaikan yang ini - Parse SDK untuk Android tidak dilengkapi dengan dukungan bawaan dalam sertifikat SelfSigned. Anda perlu memodifikasi kodenya sendiri.

Langkah Pertama - Potongan kode yang relevan ada di ParseHttpClient

  public static ParseHttpClient createClient(int socketOperationTimeout,
      SSLSessionCache sslSessionCache) {
    String httpClientLibraryName;
    ParseHttpClient httpClient;
    if (hasOkHttpOnClasspath()) {
      httpClientLibraryName = OKHTTP_NAME;
      httpClient =  new ParseOkHttpClient(socketOperationTimeout, sslSessionCache);
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
      httpClientLibraryName = URLCONNECTION_NAME;
      httpClient =  new ParseURLConnectionHttpClient(socketOperationTimeout, sslSessionCache);
    } else {
      httpClientLibraryName = APACHE_HTTPCLIENT_NAME;
      httpClient =  new ParseApacheHttpClient(socketOperationTimeout, sslSessionCache);
    }
    PLog.i(TAG, "Using " + httpClientLibraryName + " library for networking communication.");
    return httpClient;   }

Jika dukungan target Anda adalah untuk versi yang lebih maju maka KITKAT - Maka Anda perlu menambahkan konstruktor ParseURLConnectionHttpClient:

    HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier(){

            public boolean verify(String hostname, SSLSession session) {
                if(hostname.equals("YOUR TARGET SERVER")) {
                    return true;
                }
                return false;
            }});

Dalam kasus lain (versi lama) kode akan jatuh ke Apache, saya tidak dapat bekerja dengannya- jadi saya melakukan hal berikut: Saya menambahkan perpustakaan okhttp ke aplikasi saya (ambil versi 2.4 - parse yang sama menunjukkan di build , yang terbaru memiliki nama paket yang berbeda) dan kemudian kode akan masuk ke kondisi pertama karena akan menemukan okhttp di Path. Anda mungkin harus mengganti urutan kondisi if sehingga ini hanya akan terjadi pada versi yang lebih rendah dari KITKAT.

Di ParseOkHttpClient tambahkan kode sertifikat yang ditandatangani sendiri berikut:

   public void initCert() {
    try {
        Log.i("PARSE","initCert");

        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        String yairCert = "-----BEGIN CERTIFICATE-----\n" +
                YOUR CERTIFICATE HERE
                "-----END CERTIFICATE-----\n";
        InputStream caInput = new ByteArrayInputStream(yairCert.getBytes());
        Certificate ca = null;
        try {
            ca = cf.generateCertificate(caInput);
            System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
        } catch (CertificateException e) {
            e.printStackTrace();
        } finally {
            try {
                caInput.close();
            } catch (IOException e) {
                Log.e("PARSE_BUG","Failure on Cert installing",e);
                e.printStackTrace();
            }
        }

        // 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);
        Log.i("PARSE","Initiating Self Signed cert");
        okHttpClient.setSslSocketFactory(context.getSocketFactory());
        try {
            cf = CertificateFactory.getInstance("X.509");
        } catch (CertificateException e) {
            Log.e("PARSE_BUG","Failure on Cert installing",e);
            e.printStackTrace();
        }
    } catch (IOException e) {
        Log.e("PARSE_BUG","Failure on Cert installing",e);
        e.printStackTrace();
    } catch (CertificateException e) {
        Log.e("PARSE_BUG","Failure on Cert installing",e);
        e.printStackTrace();

    } catch (NoSuchAlgorithmException e) {
        Log.e("PARSE_BUG","Failure on Cert installing",e);
        e.printStackTrace();
    } catch (KeyStoreException e) {
        Log.e("PARSE_BUG","Failure on Cert installing",e);
        e.printStackTrace();
    } catch (KeyManagementException e) {
        Log.e("PARSE_BUG","Failure on Cert installing",e);
        e.printStackTrace();
    }

Dan bagian terakhirnya adalah memanggil metode ini + memverifikasi nama host, ini juga harus dilakukan di Konstruktor. initCert(); okHttpClient.setHostnameVerifier(HostnameVerifier baru() { @Override public boolean verifikasi(String s, SSLSession sslSession) { if(s.equals("SERVER TARGET ANDA")) { return true; } return false; } });

Itu dia. Bangun PARSE secara lokal dan terapkan ke aplikasi Anda dan itu akan bekerja dengan sangat baik.

Menikmati

person Croc    schedule 11.07.2016