Самозаверяющий сертификат с сервером NodeJS и клиентом Android не работает

#android #node.js #android-studio #https #socket.io

Вопрос:

Преобразуйте мой сервер http Nodejs в самозаверяющий сертификат с сервером Nodejs (https), Сертификаты добавляются на мой сервер Nodejs отлично работают, но я хочу передать данные из сокета ввода-вывода в клиент Android с помощью https-сервера, он не работает, один месяц изо всех сил пытается завершить это, пожалуйста, помогите мне решить эту проблему с моим кодом. Пожалуйста, не используйте «Принять все коды сертификатов» в клиенте Android

Моя версия ввода — вывода сокета сервера — 2.4.1

Моя версия — реализация ввода — вывода для Android-клиента («io.socket:socket.io-клиент:1.0.0»

app.js

 const express = require('express')
const https = require('https')
const fs = require('fs')
const path = require('path')
const app = express()
var bodyParser = require('body-parser');
const io = require("socket.io")(https);


io.on('connection',function(socket){
    
    console.log('one user connected ' socket.id);
    socket.emit('CHAT',{"message":"hy"});
    socket.on('disconnect',function(){
        console.log('one user disconnected ' socket.id);
    });

})

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:true}));



app.use('/',(req,res,next) => {
    res.send('Hello from SSL server!!!')
})

const sslServer = https.createServer(
    {
        key: fs.readFileSync(path.join(__dirname,'cert','key.pem')),
        cert: fs.readFileSync(path.join(__dirname,'cert','cert.pem')),
    },
    app
)
sslServer.listen(3000, () => console.log("Secure Server on port 3000"))
 

Main3Activity.java

 import java.net.URISyntaxException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;
import okhttp3.OkHttpClient;

public class Main3Activity extends AppCompatActivity {
    X509TrustManager trustManager;
    OkHttpClient okHttpClient;
    SSLSocketFactory sslSocketFactory;
    String message;
    final String uri = "https://192.XXX.43.XXX:3000";
    private Socket mSocket;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);

        try {
            trustManager = trustManagerForCertificates(trustedCertificatesInputStream());
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, new TrustManager[]{trustManager}, null);
            sslSocketFactory = sslContext.getSocketFactory();

        } catch (GeneralSecurityException e) {
            throw new RuntimeException(e);
        }

        try {

            okHttpClient = new OkHttpClient.Builder()
                    .hostnameVerifier((hostname, session) -> true)
                    .sslSocketFactory(sslSocketFactory, trustManager)
                    .connectTimeout(45, TimeUnit.SECONDS)
                    .readTimeout(45, TimeUnit.SECONDS)
                    .build();

            IO.setDefaultOkHttpWebSocketFactory(okHttpClient);
            IO.setDefaultOkHttpCallFactory(okHttpClient);
            IO.Options opts = new IO.Options();
            opts.callFactory = okHttpClient;
            opts.webSocketFactory = okHttpClient;

            mSocket = IO.socket(uri,opts);
            mSocket.on("CHAT", onNewMessage);
            mSocket.connect();

        } catch (URISyntaxException e) {}

    }

    private Emitter.Listener onNewMessage = new Emitter.Listener() {
        @Override
        public void call(final Object... args) {
            try {
                JSONObject data = (JSONObject) args[0];
                message = data.getString("message");
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Log.e("Values",message);
                    }
                });

            } catch (JSONException e) {
                return;
            }
        }
    };
    private InputStream trustedCertificatesInputStream() {
        return getApplicationContext().getResources().openRawResource(R.raw.cert);
    }
    private X509TrustManager trustManagerForCertificates(InputStream in)
            throws GeneralSecurityException {
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        Collection<? extends Certificate> certificates = certificateFactory.generateCertificates(in);
        if (certificates.isEmpty()) {
            throw new IllegalArgumentException("expected non-empty set of trusted certificates");
        }

        // Put the certificates a key store.
        char[] password = "password".toCharArray(); // Any password will work.
        KeyStore keyStore = newEmptyKeyStore(password);
        int index = 0;
        for (Certificate certificate : certificates) {
            String certificateAlias = Integer.toString(index  );
            keyStore.setCertificateEntry(certificateAlias, certificate);
        }

        // Use it to build an X509 trust manager.
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(
                KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, password);
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
                TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(keyStore);
        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
        if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
            throw new IllegalStateException("Unexpected default trust managers:"
                      Arrays.toString(trustManagers));
        }
        return (X509TrustManager) trustManagers[0];
    }

    private KeyStore newEmptyKeyStore(char[] password) throws GeneralSecurityException {
        try {
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            InputStream in = null; // By convention, 'null' creates an empty key store.
            keyStore.load(in, password);
            return keyStore;
        } catch (IOException e) {
            throw new AssertionError(e);
        }
    }
}
 

Комментарии:

1. Для современных версий Android есть более простые способы добавить пользовательский самозаверяющий сертификат с помощью network_security_config.xml — просто поместите простой сертификат в качестве исходного ресурса в свой проект: developer.android.com/training/articles/…