emqx ssl双向认证无法建立连接

按照文档生成了自签名证书
在服务端控制台配置了证书,并且开启了客户端验证
使用mqttx工具配置客户端证书连接成功
按照列子 https://github.com/emqx/MQTT-Client-Examples/blob/master/mqtt-client-Java/src/main/java/io/emqx/mqtt/MqttTwoWayTlsSample.java 无法建立连接

服务端日志

   2024-02-22T17:43:40.695000+08:00 [notice] TLS server: In state certify at ssl_handshake.erl:2109 generated SERVER ALERT: Fatal - Bad Certificate
2024-02-22T17:43:40.695000+08:00 [notice] supervisor: {esockd_connection_sup,<0.3009.0>}, errorContext: ssl_error, reason: {tls_alert,{bad_certificate,"TLS server: In state certify at ssl_handshake.erl:2109 generated SERVER ALERT: Fatal - Bad Certificate\n"}}, offender: [{pid,<0.3009.0>},{name,connection},{mfargs,{emqx_connection,start_link,[#{enable_authn => true,limiter => undefined,listener => {ssl,default},zone => default}]}}]

java客户端代码

            SSLSocketFactory socketFactory = SSLUtils.getSocketFactory(sslCaFilePath, sslCrtFilePath, sslKeyFilePath, "");
            //SSLSocketFactory socketFactory = getSSLSocketFactory(sslCrtFilePath, sslKeyFilePath, sslCaFilePath);

            MemoryPersistence persistence = new MemoryPersistence();
            MqttClient client = new MqttClient(broker, serverClientId + "-" + System.currentTimeMillis(), persistence);
            MqttConnectOptions connOpts = new MqttConnectOptions();
            connOpts.setUserName(username);
            connOpts.setPassword(password.toCharArray());
            connOpts.setCleanSession(true);
            connOpts.setAutomaticReconnect(true);
            connOpts.setKeepAliveInterval(10);
            connOpts.setConnectionTimeout(60);
            connOpts.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1);
            connOpts.setSocketFactory(socketFactory);

            client.connect(connOpts);
    public static SSLSocketFactory getSocketFactory(final String caCrtFile,
                                                    final String crtFile, final String keyFile, final String password)
            throws Exception {
        Security.addProvider(new BouncyCastleProvider());

        // Load CA certificates
        KeyStore caKs = loadCAKeyStore(caCrtFile);

        // Load client certificate chain and key
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(null, null);

        // Load the entire client certificate chain
        Certificate[] chain;
        try (FileInputStream fis = new FileInputStream(crtFile)) {
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            Collection<? extends Certificate> certs = cf.generateCertificates(fis);
            chain = certs.toArray(new Certificate[0]);
        }

        // Load client private key
        try (PEMParser pemParser = new PEMParser(new FileReader(keyFile))) {
            Object object = pemParser.readObject();
            JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
            PrivateKey key = converter.getPrivateKey((PrivateKeyInfo) object);
            ks.setKeyEntry("private-key", key, password.toCharArray(), chain);
        }

        // Set up key managers and trust managers
        TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
        tmf.init(caKs);
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(ks, password.toCharArray());

        // finally, create SSL socket factory
        SSLContext context = SSLContext.getInstance("TLSv1.2");
        context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

        return context.getSocketFactory();
    }

仔细检查过证书文件路径和在mqttx工具中配置的client.crt client.key root.crt路径是一样的,mqttx可以建立连接 但是 java客户端无法建立连接

这个错误还是说证书有问题。你可以参照这个文档自己生成证书:

但我建议你去互联网上搜索一个一键生成一套证书的脚本,这样就省去很多麻烦。

使用nginx终结可以连上了