Android Https запрос с использованием Volley и проблема с самозаверяющим сертификатом [решено]

У меня есть экспресс-сервер NodeJS, и я хочу отправить ему запрос Https через устройство Android.

В настоящее время мне удается просматривать веб-сайт Https через Chrome.

Это мой код Node JS:

const https = require('https');
const fs = require('fs');

const credentials = {
    key: fs.readFileSync(__dirname + '/ssl/domain.key', 'utf8'),
    cert: fs.readFileSync(__dirname + '/ssl/domain.crt', 'utf8')
};

let port = '443';

const server = https.createServer(credentials, app);
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

...

app.get("/connect", function(req, res){
    ...
});

На стороне Android я попробовал эти решения:

https://newfivefour.com/android-trust-all-ssl-certificates.html

/questions/15426909/android-volley-self-podpisannyij-sertifikat/15426918#15426918

/questions/2667333/svyaz-cherez-veb-servis-android-https-ssl-tls-12/2667355#2667355

Но я продолжаю получать эту ошибку:

com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: Connection closed by peer with params [...]
    at com.android.volley.Request.deliverError(Request.java:617)
    at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:104)
    at android.os.Handler.handleCallback(Handler.java:873)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:193)
    at android.app.ActivityThread.main(ActivityThread.java:6669)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

Я попытался использовать сервер TLS вместо:

const tls = require('tls'); // instead https

Но я получил ту же ошибку... Я новичок в мире Https, поэтому я думаю, что это проблема конфигурации мисс...

Как я могу решить эту проблему?

Благодарю.

Решение

Я использовал этот код:

fun newSSLSocketFactory(context: Context): SSLSocketFactory {
    // Load CAs from an InputStream
    // (could be from a resource or ByteArrayInputStream or ...)
    val cf: CertificateFactory = CertificateFactory.getInstance("X.509")
    // From https://www.washington.edu/itconnect/security/ca/load-der.crt
    val caInput: InputStream = context.resources.openRawResource(R.raw.domain)
    val ca: X509Certificate = caInput.use {
        cf.generateCertificate(it) as X509Certificate
    }

    // Create a KeyStore containing our trusted CAs
    val keyStoreType = KeyStore.getDefaultType()
    val keyStore = KeyStore.getInstance(keyStoreType).apply {
        load(null, null)
        setCertificateEntry("ca", ca)
    }

    // Create a TrustManager that trusts the CAs inputStream our KeyStore
    val tmfAlgorithm: String = TrustManagerFactory.getDefaultAlgorithm()
    val tmf: TrustManagerFactory = TrustManagerFactory.getInstance(tmfAlgorithm).apply {
        init(keyStore)
    }

    // Create an SSLContext that uses our TrustManager
    val sslContext: SSLContext = SSLContext.getInstance("TLS").apply {
        init(null, tmf.trustManagers, null)
    }

    val defValidator = HttpsURLConnection.getDefaultHostnameVerifier()
    HttpsURLConnection.setDefaultHostnameVerifier { hostname, session ->
        if (hostname == BuildConfig.SERVER_IP) {
            true
        } else {
            defValidator.verify(hostname, session)
        }
    }

    // Tell the URLConnection to use a SocketFactory from our SSLContext
    return sslContext.socketFactory
}

и залпом:

Volley.newRequestQueue(context, HurlStack(null, NetworkHelper.newSSLSocketFactory(context)))

0 ответов

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