天天看點

android用戶端使用ssl連接配接mqtt伺服器(單向認證)不含證書

https://www.cnblogs.com/csswzp/p/8615516.html

android用戶端使用ssl連接配接mqtt伺服器(單向認證)

單向認證,用戶端可以含證書也可以不含證書

一、包含證書方式

1,由于android需要bks格式證書,是以我們需要先生成。

1.1 拿到服務端證書

1.2 下載下傳 bcprov-ext-jdkxxx.jar,把jar放入C:\Program Files\Java\jre1.8.0_131\lib\ext

官網位址:http://www.bouncycastle.org/latest_releases.html

1.3 打開cmd,進入C:\Program Files\Java\jre1.8.0_131\bin目錄

輸入指令:keytool -importcert -trustcacerts -keystore "想生成證書的名字和路徑" -file “服務端證書路徑” -storetype BKS -provider        org.bouncycastle.jce.provider.BouncyCastleProvider  
           

2,這樣就生成了我們需要的證書,寫連接配接函數

public boolean start() {

        boolean ret ;
        try {

            MqttConnectOptions conOpt = new MqttConnectOptions();
            // host為主機名,clientid即連接配接MQTT的用戶端ID,一般以唯一辨別符表示,MemoryPersistence設定clientid的儲存形式,預設為以記憶體儲存  
            client = new MqttClient(“ssl://ip:端口号”, clientid, new MemoryPersistence());

            SSLContext sc = SSLContext.getInstance("SSL");
            KeyStore ts = KeyStore.getInstance("BKS");
        //讀取剛才生成的bks檔案,還有生成時密鑰庫密碼
            ts.load(context.getAssets().open("key.bks"), "123456".toCharArray());

            TrustManagerFactory tmf = TrustManagerFactory
                    .getInstance("X509");
            tmf.init(ts);
            TrustManager[] tm = tmf.getTrustManagers();
            sc.init(null, tm, new SecureRandom());
            SocketFactory factory = sc.getSocketFactory();
            conOpt.setSocketFactory(factory);

            // MQTT的連接配接設定
 
              // 設定是否清空session,這裡如果設定為false表示伺服器會保留用戶端的連接配接記錄,這裡設定為true表示每次連接配接到伺服器都以新的身份連接配接
            conOpt.setCleanSession(true);
                        // 設定連接配接的使用者名
            conOpt.setUserName(userName);
                        // 設定連接配接的密碼
            conOpt.setPassword(NewPassWord.toCharArray());
                        // 設定逾時時間 機關為秒
            conOpt.setConnectionTimeout(5);
                        // 設定會話心跳時間 機關為秒 伺服器會每隔1.5*20秒的時間向用戶端發送個消息判斷用戶端是否線上,但這個方法并沒有重連的機制
            conOpt.setKeepAliveInterval(20);
                        // 設定回調
                        client.setCallback(new PushCallback(context));
                        MqttTopic topic = client.getTopic(TOPIC);
                        //setWill方法,如果項目中需要知道用戶端是否掉線可以調用該方法。設定最終端口的通知消息
            conOpt.setWill(topic, "close".getBytes(), 0, false);

            client.connect(conOpt);

            //訂閱消息  
            int[] Qos  = {0,0};
            //TOPIC,
            String[] topic1 = {TOPIC,"Public"};
            client.subscribe(topic1, Qos);
            ret=true;
        } catch (Exception e) {
            ret=false;
            e.printStackTrace();  
            try {
               if(client.isConnected())
                  client.disconnect();
         } catch (MqttException e1) {
            e1.printStackTrace();
         }
        }
        return ret;
    }
    
           

再加入釋出和接受函數就可以實作收發消息了

二、不含證書方式

不含證書需要跳過證書驗證部分,重寫TrustManager,具體代碼如下
           
static class miTM implements TrustManager, X509TrustManager {
    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }

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

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

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

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

//連接配接函數
  public boolean start() {

        boolean ret ;
        try {

            MqttConnectOptions conOpt = new MqttConnectOptions();
            // host為主機名,clientid即連接配接MQTT的用戶端ID,一般以唯一辨別符表示,MemoryPersistence設定clientid的儲存形式,預設為以記憶體儲存  
            client = new MqttClient(“ssl://ip:端口号”, clientid, new MemoryPersistence());

    TrustManager[] trustAllCerts = new TrustManager[1];
    TrustManager tm = new miTM();
    trustAllCerts[0] = tm;
    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, null);
    SocketFactory factory = sc.getSocketFactory();
    conOpt.setSocketFactory(factory);


            // MQTT的連接配接設定
 
              // 設定是否清空session,這裡如果設定為false表示伺服器會保留用戶端的連接配接記錄,這裡設定為true表示每次連接配接到伺服器都以新的身份連接配接
            conOpt.setCleanSession(true);
                        // 設定連接配接的使用者名
            conOpt.setUserName(userName);
                        // 設定連接配接的密碼
            conOpt.setPassword(NewPassWord.toCharArray());
                        // 設定逾時時間 機關為秒
            conOpt.setConnectionTimeout(5);
                        // 設定會話心跳時間 機關為秒 伺服器會每隔1.5*20秒的時間向用戶端發送個消息判斷用戶端是否線上,但這個方法并沒有重連的機制
            conOpt.setKeepAliveInterval(20);
                        // 設定回調
                        client.setCallback(new PushCallback(context));
                        MqttTopic topic = client.getTopic(TOPIC);
                        //setWill方法,如果項目中需要知道用戶端是否掉線可以調用該方法。設定最終端口的通知消息
            conOpt.setWill(topic, "close".getBytes(), 0, false);

            client.connect(conOpt);

            //訂閱消息  
            int[] Qos  = {0,0};
            //TOPIC,
            String[] topic1 = {TOPIC,"Public"};
            client.subscribe(topic1, Qos);
            ret=true;
        } catch (Exception e) {
            ret=false;
            e.printStackTrace();  
            try {
               if(client.isConnected())
                  client.disconnect();
         } catch (MqttException e1) {
            e1.printStackTrace();
         }
        }
        return ret;
    }