如何修复没有与 IP 地址匹配的主题备用名称

Anu*_*nup 0 java ssl mqtt

我使用以下代码进行 Mqtt 客户端:基于证书的身份验证,用于在 VMware 中运行的 MQTT 代理。我正在通过 Windows 系统中的代码运行 Mqtt 客户端。

public class TestClient {

public static void main(String[] args) {
        String serverUrl = "ssl://192.168.5.12:8883";
        String caFilePath = "rootca.pem";
        String clientCrtFilePath = "Client.pem";
        String clientKeyFilePath = "Client.key";
        String mqttUserName = "guest";
        String mqttPassword = "123123";
        
        MqttClient client;
        try {
            client = new MqttClient(serverUrl, "2");
            MqttConnectOptions options = new MqttConnectOptions();
//          options.setUserName(mqttUserName);
//          options.setPassword(mqttPassword.toCharArray());
//          options.setSSLProperties(props);
            options.setConnectionTimeout(0);
            options.setKeepAliveInterval(300);
            options.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1);

            SSLSocketFactory socketFactory = getSocketFactory(caFilePath,
                    clientCrtFilePath, clientKeyFilePath, "");
            options.setSocketFactory(socketFactory);

            System.out.println("starting connect the server...");
            client.connect(options);
            System.out.println("connected!");
            Thread.sleep(1000);

            client.subscribe(
                    "/u/56ca327d17531d08e76bddd4a215e37f5fd6082f7442151c4d3f1d100a0ffd4e",
                    0);
            client.disconnect();
            System.out.println("disconnected!");
        } catch (MqttException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static SSLSocketFactory getSocketFactory(final String caCrtFile,
            final String crtFile, final String keyFile, final String password)
            throws Exception {
        Security.addProvider(new BouncyCastleProvider());
        // load CA certificate
        X509Certificate caCert = null;
        FileInputStream fis = new FileInputStream(caCrtFile);
        BufferedInputStream bis = new BufferedInputStream(fis);
        CertificateFactory cf = CertificateFactory.getInstance("X.509");

        while (bis.available() > 0) {
            caCert = (X509Certificate) cf.generateCertificate(bis);
            // System.out.println(caCert.toString());
        }
        // load client certificate
        bis = new BufferedInputStream(new FileInputStream(crtFile));
        X509Certificate cert = null;
        while (bis.available() > 0) {
            cert = (X509Certificate) cf.generateCertificate(bis);
            // System.out.println(caCert.toString());
        }
        // load client private key
        PEMParser pemParser = new PEMParser(new FileReader(keyFile));
        Object object = pemParser.readObject();
        PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder()
                .build(password.toCharArray());
        JcaPEMKeyConverter converter = new JcaPEMKeyConverter()
                .setProvider("BC");
        KeyPair key;
        if (object instanceof PEMEncryptedKeyPair) {
            System.out.println("Encrypted key - we will use provided password");
            key = converter.getKeyPair(((PEMEncryptedKeyPair) object)
                    .decryptKeyPair(decProv));
        } else {
            System.out.println("Unencrypted key - no password needed");
            key = converter.getKeyPair((PEMKeyPair) object);
        }
        pemParser.close();

        // CA certificate is used to authenticate server
        KeyStore caKs = KeyStore.getInstance(KeyStore.getDefaultType());
        caKs.load(null, null);
        caKs.setCertificateEntry("ca-certificate", caCert);
        TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
        tmf.init(caKs);

        // client key and certificates are sent to server so it can authenticate
        // us
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(null, null);
        ks.setCertificateEntry("certificate", cert);
        ks.setKeyEntry("private-key", key.getPrivate(), password.toCharArray(),
                new java.security.cert.Certificate[] { cert });
        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();
    }
  }
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:IP 地址没有主题备用名称匹配

Unencrypted key - no password needed
starting connect the server...
MqttException (0) - javax.net.ssl.SSLHandshakeException: No subject alternative names matching IP address 192.168.5.12 found
    
Run Code Online (Sandbox Code Playgroud)

我搜索了很多我无法修复它请帮助谢谢

har*_*llb 5

这里你有 3 个选择。

  1. 更改代理提供的证书,它需要包含 IP 地址的 SAN(主题备用名称)条目。
  2. 更改您在客户端中使用的代理 URL,以使用代理的 SAN 或 CN 字段中已有的内容。
  3. 告诉您的应用程序不要验证远程代理证书。这是通过修改 SocketFactory 代码来完成的,您已经必须包含一个自定义的 TrustManager,它不会检查主机名/IP 是否与证书匹配。

选项 1/2 可能是最简单的(假设您创建了代理正在使用的证书),选项 3 很危险,因为您不希望此代码溜到生产中,因为它会让某人更容易在中间攻击