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;
}

 



 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM