我正在使用react_native_mqtt,需要在客户端和服务器之间实现安全的mqtt通信

问题描述 投票:0回答:2

连接到 mqtt 服务器时,我将 useSSL 设置为 true。 443端口正在被使用。

我需要在此调用中使用 SSL 固定,设置 useSSL 标志是否足够?

如果没有,请建议我使用 SSL 固定来安全地连接服务器的方式。

我没有对react_native_mqtt库中与证书固定相关的任何内容进行罚款。

此外,建议使用节点的 tls.connect() 进行连接的库之一。如果有人用过这个请分享。

谢谢

ssl websocket mqtt certificate-pinning react-native-mqtt
2个回答
0
投票

我也面临着同样的问题,我所做的是添加附加字段来连接

client.connect({ onSuccess: onConnect, useSSL: true ,userName:"brokerUsername", password:"brokerPassword" })
这对我有用。


0
投票

我知道我对这个讨论有点晚了,但我想分享我在互联网上搜索了很多但没有找到任何可用的东西后提出的解决方案。我希望这对其他人有帮助。

问题:如何在不绑定证书的情况下在React Native中建立安全的MQTT连接?

以下是有关如何使用自定义 Java 包在 React Native 应用程序中设置安全 MQTT 连接的分步指南。当您不想直接绑定证书时,此方法适合:

第 1 步:创建 Java 文件

首先,在你的React Native项目中的目录下创建两个Java文件:

android/app/main/java/com/[yourappname]/mqtt/

  1. MQTTClientModule.java
  2. MQTTClientPackage.java

第2步:实现MQTTClientModule.java

package com.yourappname.mqtt;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;
import java.security.NoSuchAlgorithmException;
import java.security.KeyManagementException;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import android.util.Log;

public class MQTTClientModule extends ReactContextBaseJavaModule implements MqttCallback {
    private MqttClient client;
    private MqttConnectOptions options;
    private ReactApplicationContext reactContext;
    private String topic;

    private String serverUri;
    private String clientId;
    private String username;
    private String password;
    private boolean trustAll;

    public MQTTClientModule(ReactApplicationContext context) {
        super(context);
        this.reactContext = context;
    }

    @Override
    public String getName() {
        return "MQTTClientModule";
    }

    @ReactMethod
    public void initialize(String serverUri, String clientId, String username, String password, boolean trustAll) {
        try {

            this.serverUri = serverUri;
            this.clientId = clientId;
            this.username = username;
            this.password = password;
            this.trustAll = trustAll;

            MqttConnectOptions options = new MqttConnectOptions();
            options.setCleanSession(true);
            options.setUserName(this.username);
            options.setPassword(this.password.toCharArray());
            if (trustAll && (this.serverUri.startsWith("ssl://") || this.serverUri.startsWith("wss://"))) {
                SSLContext sc = SSLContext.getInstance("SSL");
                sc.init(null, new TrustManager[] { new X509TrustManager() {
                    public void checkClientTrusted(X509Certificate[] chain, String authType) {
                    }

                    public void checkServerTrusted(X509Certificate[] chain, String authType) {
                    }

                    public X509Certificate[] getAcceptedIssuers() {
                        return new X509Certificate[0];
                    }
                } }, new java.security.SecureRandom());
                options.setSocketFactory(sc.getSocketFactory());
            }

            this.client = new MqttClient(this.serverUri, this.clientId, new MemoryPersistence());
            this.client.setCallback(this);
            this.client.connect(options);
            sendEvent("onSuccess", "Mqtt Connected");
        } catch (MqttException | NoSuchAlgorithmException | KeyManagementException e) {
            sendEvent("onError", e.toString());
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void disconnect() {
        try {
            if (client != null) {
                client.disconnect();
            }
        } catch (MqttException e) {
            sendEvent("onError", e.toString());
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void subscribe(String topic) {
        try {
            this.topic = topic;
            client.subscribe(this.topic);
            sendEvent("onSuccess", "Subscribed to " + topic);
        } catch (MqttException e) {
            sendEvent("onError", e.toString());
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void publish(String topic, String message) {
        try {
            client.publish(topic, new MqttMessage(message.getBytes()));
            sendEvent("onSuccess", "Message Published");

        } catch (MqttException e) {
            sendEvent("onError", e.toString());
            e.printStackTrace();
        }
    }

    @Override
    public void connectionLost(Throwable cause) {
        try {
            sendEvent("onError", cause.toString());
            sendEvent("onError", "Trying to reconnect...");
            MqttConnectOptions options = new MqttConnectOptions();
            options.setCleanSession(true);
            options.setUserName(this.username);
            options.setPassword(this.password.toCharArray());
            if (trustAll && (this.serverUri.startsWith("ssl://") || this.serverUri.startsWith("wss://"))) {
                SSLContext sc = SSLContext.getInstance("SSL");
                sc.init(null, new TrustManager[] { new X509TrustManager() {
                    public void checkClientTrusted(X509Certificate[] chain, String authType) {
                    }

                    public void checkServerTrusted(X509Certificate[] chain, String authType) {
                    }

                    public X509Certificate[] getAcceptedIssuers() {
                        return new X509Certificate[0];
                    }
                } }, new java.security.SecureRandom());
                options.setSocketFactory(sc.getSocketFactory());
            }

            this.client = new MqttClient(this.serverUri, this.clientId, new MemoryPersistence());
            this.client.setCallback(this);
            this.client.connect(options);
            sendEvent("onSuccess", "Mqtt Reconnected");
            if (this.topic != null) {
                this.client.subscribe(this.topic);
                sendEvent("onSuccess", "Resubscribed to " + this.topic);
            }
        } catch (MqttException | NoSuchAlgorithmException | KeyManagementException e) {
            sendEvent("onError", e.toString());
            e.printStackTrace();
        }
    }

    @Override
    public void messageArrived(String topic, MqttMessage message) {
        sendEvent("messageArrived", new String(message.getPayload()));
    }

    @Override
    public void deliveryComplete(IMqttDeliveryToken token) {
        sendEvent("deliveryComplete", token.toString());
    }

    private void sendEvent(String eventName, String eventData) {
        reactContext
                .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit(eventName, eventData);
    }
}

第3步:实现MQTTClientPackage.java

package com.yourappname.mqtt;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class MQTTClientPackage implements ReactPackage {

    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new MQTTClientModule(reactContext));
        return modules;
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}

第 4 步:在 React Native 中使用模块

import React, { useEffect, useRef } from 'react';
import { NativeModules, NativeEventEmitter } from 'react-native';
import { createContextHook } from 'use-context-hook';
import { MQTT_PASSWORD, MQTT_URL, MQTT_USER_NAME } from '../services/endpoints';

const { MQTTClientModule } = NativeModules;
const mqttEventEmitter = new NativeEventEmitter(MQTTClientModule);

const MQTTContext = createContextHook();

export const MQTTProvider = ({ children }) => {
    useEffect(() => {
        const messageListener = mqttEventEmitter.addListener('messageArrived', msg => {
            let { type, ...payload } = JSON.parse(msg);
            messageHandler({ type, ...payload });
        });
        const onSuccessListener = mqttEventEmitter.addListener('onSuccess', msg => {
            console.log(msg);
        });

        const errorListener = mqttEventEmitter.addListener('onError', msg => {
            console.log(msg);
        });
        MQTTClientModule.initialize(MQTT_URL, new Date().getTime().toString(), MQTT_USER_NAME, MQTT_PASSWORD, true);
        MQTTClientModule.subscribe('testTopic');

        return () => {
            messageListener.remove();
            errorListener.remove();
            onSuccessListener.remove();
        };
    }, []);

    const publish = (topic, msg) => {
        MQTTClientModule.publish(topic, msg);
    };
    const messageHandler = ({ type, ...payload }) => {
        console.log(type, payload);
    };

    return <MQTTContext.Provider value={{ publish }}>{children}</MQTTContext.Provider>;
};

补充说明:

  • 对于生产环境,请考虑通过正确集成 SSL 证书来保护您的连接,而不是信任所有证书。
  • 不要忘记将新包包含在 Android 项目的
    MainApplication.java
    文件中。
© www.soinside.com 2019 - 2024. All rights reserved.