Emqtt的ssl/tls加密

繼上個星期以後,這個星期有花了兩三天的時間來搞emqtt的ssl/tls加密。html

主流程仍是參考了:https://blog.csdn.net/a704397849/article/details/88885198#commentsedit, 到最後一步用mosquitto_sub訂閱消息的時候始終有問題:java

聯繫了參考文章的做者,而且加了QQ,想不到是個很熱情的人。他從新走了一下流程而且肯定是沒有問題的,給了我一份客戶端的代碼:mysql

package com.zkong.mqttssl;

import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;

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

public class MqttTLSTest {

    static MqttClientCallback mqttClientCallback = new MqttClientCallback();
    static MqttAsyncClient mqttClient = null;

    static String username = "stan";  //注意這裏 填你本身的mqtt帳號密碼
    static String password = "123456"; //注意這裏 填你本身的mqtt帳號密碼
    //String broker = "tcp://xxx.xx.xxx.xxx:1883"; //注意這裏要填本身mqtt服務器所在地址
    static String broker = "ssl://192.168.100.117:8883"; //注意這裏要填本身mqtt服務器所在地址

    public static void main(String[] args) throws InterruptedException {
        start();
        while (true){
            Thread.sleep(10000);
        }
    }

    public static void start() {
        String clientId = "mqttserver" + String.valueOf(System.currentTimeMillis());

        try {
            mqttClient = new MqttAsyncClient(broker, clientId, new MemoryPersistence());
            mqttClient.setCallback(mqttClientCallback);

            //訂閱 鏈接mqtt服務器
            subscribeConnect();

            //發佈 鏈接mqtt服務器
            //... 略

        } catch (MqttException me) {
            System.out.println("reason " + me.getReasonCode());
            System.out.println("msg " + me.getMessage());
            System.out.println("loc " + me.getLocalizedMessage());
            System.out.println("cause " + me.getCause());
            System.out.println("excep " + me);
            me.printStackTrace();
        }
    }

    public static void subscribeConnect() {
        System.out.println("訂閱鏈接");
        if (mqttClient != null) {
            try {
                MqttConnectOptions connOpts = new MqttConnectOptions();

                connOpts.setCleanSession(true);
                connOpts.setMaxInflight(100000);

                connOpts.setUserName(username);
                connOpts.setPassword(password.toCharArray());

                //ssl 鏈接 , 這裏的 TrustManager 是本身實現的,沒有去校驗服務端的證書
                TrustManager[] trustAllCerts = new TrustManager[1];
                TrustManager tm = new MyTM();
                trustAllCerts[0] = tm;
                SSLContext sc = SSLContext.getInstance("SSL");
                sc.init(null, trustAllCerts, null);
                SocketFactory factory = sc.getSocketFactory();
                connOpts.setSocketFactory(factory);
                //

                mqttClient.connect(connOpts, null, new IMqttActionListener() {
                    @Override
                    public void onSuccess(IMqttToken asyncActionToken) {
                        try {
                            //訂閱 topic 爲test 的消息,消息質量1
                            mqttClient.subscribe("test", 1);
                        } catch (MqttException me) {
                            System.out.println("reason " + me.getReasonCode());
                            System.out.println("msg " + me.getMessage());
                            System.out.println("loc " + me.getLocalizedMessage());
                            System.out.println("cause " + me.getCause());
                            System.out.println("excep " + me);
                            me.printStackTrace();
                        }
                    }

                    @Override
                    public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                        System.out.println("mqtt 沒有鏈接上:" + exception.getMessage());
                        exception.printStackTrace();
                    }
                });
            } catch (MqttException me) {
                System.out.println("reason " + me.getReasonCode());
                System.out.println("msg " + me.getMessage());
                System.out.println("loc " + me.getLocalizedMessage());
                System.out.println("cause " + me.getCause());
                System.out.println("excep " + me);
                me.printStackTrace();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (KeyManagementException e) {
                e.printStackTrace();
            }
        }
    }

    //MyTM 是本身實現的認證管理類,裏面並有校驗服務端的證書就返回true,永久成功!
    static class MyTM implements TrustManager, X509TrustManager {
        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        public boolean isServerTrusted(X509Certificate[] certs) {
            return true;
        }

        public boolean isClientTrusted(X509Certificate[] certs) {
            return true;
        }

        @Override
        public void checkServerTrusted(X509Certificate[] certs, String authType)
                throws CertificateException {
            return;
        }

        @Override
        public void checkClientTrusted(X509Certificate[] certs, String authType)
                throws CertificateException {
            return;
        }
    }

    public static class MqttClientCallback implements MqttCallback{

        @Override
        public void connectionLost(Throwable arg0)
        {
            System.out.println("mqtt 失去了鏈接");
        }

        @Override
        public void deliveryComplete(IMqttDeliveryToken arg0)
        {
            System.out.println("mqtt 發送完成!");
        }

        @Override
        public void messageArrived(String topic, MqttMessage message)
                throws Exception
        {
            String content = new String(message.getPayload(), "utf-8");
            System.out.println("收到mqtt消息,topic: "+topic+" ,content: "+content);
        }
    }
}

用這份客戶端代碼訂閱消息,是沒有問題的,由於個人服務器開啓了基於mysql的認證,因此必須提供username和password。sql

要完全走通的,估計還得找一臺乾淨的機器從新安裝emqtt。windows

有些問題在此記錄一下:服務器

關於mosquittoeclipse

它跟emqtt同樣,自己也是一個mqtt的broker,在windows上安裝完以後做爲一個服務存在,當它處於啓動狀態時,會佔掉1883端口致使emqtt沒法徹底啓動,能夠在Windows的服務管理中將其關閉:async

Centos7上安裝openssltcp

http://www.javashuo.com/article/p-muqouusg-eb.htmlide

Centos7上安裝mosquitto

http://www.javashuo.com/article/p-mppgavlk-mw.html

 

未走通流程:

雙向認證:https://blog.csdn.net/zljintan/article/details/83619309

自帶證書驗證(使用MQTTBox做爲客戶端):http://www.javashuo.com/article/p-nbzatlbi-gq.html

相關文章
相關標籤/搜索