閱讀139 返回首頁    go 阿裏雲 go 技術社區[雲棲]


SSL 方式接入示例__Java 接入示例_MQTT 接入(物聯)_消息隊列 MQ-阿裏雲

本文主要介紹如何使用 MQTT 的 SSL 加密通道來收發消息。

注意:

SSL 方式接入需要服務端支持,目前各個 Region 對 SSL 通道的支持情況請參考環境準備章節的文檔。

本文給出的示例均基於 Eclipse Paho Java SDK 實現,SDK 下載請參見 MQTT 接入準備。如使用其他第三方的客戶端,請適當修改。

1. 證書下載

如果需要使用 SSL 加密通道,需要首先下載服務端的安全證書到本地。證書下載請點擊證書下載

2. 客戶端設置 SSL 屬性

在添加好本地的信任證書倉庫後,應用的代碼中即可設置該倉庫到 SSL 的屬性中。具體示例如下:

  1. public static void main(String[] args) throws IOException {
  2. /**
  3. * 設置MQTT的接入點,請根據應用所在環境選擇合適的Region,不支持跨Region訪問
  4. */
  5. final String broker ="ssl://mqtt-test.cn-qingdao.aliyuncs.com:8883";
  6. /**
  7. * 設置阿裏雲的AccessKey,用於鑒權
  8. */
  9. final String acessKey ="XXXXXX";
  10. /**
  11. * 設置阿裏雲的SecretKey,用於鑒權
  12. */
  13. final String secretKey ="XXXXXXX";
  14. /**
  15. * 發消息使用的一級Topic,需要先在MQ控製台裏申請
  16. */
  17. final String topic ="XXXX";
  18. /**
  19. * MQTT的ClientID,一般由兩部分組成,GroupID@@@DeviceID
  20. * 其中GroupID在MQ控製台裏申請
  21. * DeviceID由應用方設置,可能是設備編號等,需要唯一,否則服務端拒絕重複的ClientID連接
  22. */
  23. final String clientId ="GID_XXX@@@ClientID_XXXX";
  24. String sign;
  25. MemoryPersistence persistence = new MemoryPersistence();
  26. try {
  27. final MqttClient sampleClient = new MqttClient(broker, clientId, persistence);
  28. final MqttConnectOptions connOpts = new MqttConnectOptions();
  29. System.out.println("Connecting to broker: " + broker);
  30. /**
  31. * 計算簽名,將簽名作為MQTT的password。
  32. * 簽名的計算方法,參考工具類MacSignature,第一個參數是ClientID的前半部分,即GroupID
  33. * 第二個參數阿裏雲的SecretKey
  34. */
  35. sign = MacSignature.macSignature(clientId.split("@@@")[0], secretKey);
  36. connOpts.setUserName(acessKey);
  37. connOpts.setServerURIs(new String[] { broker });
  38. connOpts.setPassword(sign.toCharArray());
  39. connOpts.setCleanSession(false);
  40. connOpts.setKeepAliveInterval(100);
  41. /**
  42. *導入證書的路徑,生成加密連接
  43. */
  44. SocketFactory socketFactory = initSSLSocket("intermedia.crt");
  45. connOpts.setSocketFactory(socketFactory);
  46. sampleClient.setCallback(new MqttCallback() {
  47. public void connectionLost(Throwable throwable) {
  48. System.out.println("mqtt connection lost");
  49. throwable.printStackTrace();
  50. while(!sampleClient.isConnected()){
  51. try {
  52. sampleClient.connect(connOpts);
  53. } catch (MqttException e) {
  54. e.printStackTrace();
  55. }
  56. try {
  57. Thread.sleep(1000);
  58. } catch (InterruptedException e) {
  59. e.printStackTrace();
  60. }
  61. }
  62. }
  63. public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
  64. System.out.println("messageArrived:" + topic + "------" + new String(mqttMessage.getPayload()));
  65. }
  66. public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
  67. System.out.println("deliveryComplete:" + iMqttDeliveryToken.getMessageId());
  68. }
  69. });
  70. sampleClient.connect(connOpts);
  71. for (int i = 0; i < 10; i++) {
  72. try {
  73. String scontent = new Date()+"MQTT Test body" + i;
  74. final MqttMessage message = new MqttMessage(scontent.getBytes());
  75. message.setQos(0);
  76. System.out.println(i+" pushed at "+new Date()+" "+ scontent);
  77. /**
  78. *消息發送到某個主題Topic,所有訂閱這個Topic的設備都能收到這個消息
  79. * 遵循MQTT的發布訂閱規範,Topic也可以是多級Topic。此處設置了發送到二級Topic
  80. */
  81. sampleClient.publish(topic+"/notice/", message);
  82. /**
  83. * 如果發送P2P消息,二級Topic必須是“p2p”,三級Topic是目標的ClientID
  84. * 此處設置的三級Topic需要是接收方的ClientID
  85. */
  86. String p2pTopic =topic+"/p2p/GID_mqttdelay3@@@DEVICEID_001";
  87. sampleClient.publish(p2pTopic,message);
  88. } catch (Exception e) {
  89. e.printStackTrace();
  90. }
  91. }
  92. } catch (Exception me) {
  93. me.printStackTrace();
  94. }
  95. }

導入證書的方法:

  1. private static SSLSocketFactory initSSLSocket(String certFileName) throws Exception {
  2. InputStream caInput = new BufferedInputStream(ClassLoader.getSystemResourceAsStream(certFileName));
  3. CertificateFactory cf = CertificateFactory.getInstance("X.509");
  4. Certificate ca = null;
  5. try {
  6. ca = cf.generateCertificate(caInput);
  7. } catch (CertificateException e) {
  8. e.printStackTrace();
  9. } finally {
  10. caInput.close();
  11. }
  12. String keyStoreType = KeyStore.getDefaultType();
  13. KeyStore keyStore = KeyStore.getInstance(keyStoreType);
  14. keyStore.load(null, null);
  15. keyStore.setCertificateEntry("ca", ca);
  16. String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
  17. TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
  18. tmf.init(keyStore);
  19. SSLContext context = SSLContext.getInstance("TLSV1.2");
  20. context.init(null, tmf.getTrustManagers(), null);
  21. SSLSocketFactory socketFactory = context.getSocketFactory();
  22. return socketFactory;
  23. }

注意:使用 SSL 接入時,服務端的地址協議請設置為 ssl://XXX,不要使用 tcp://XXX,其他部分的設置和非加密通道一致即可。

最後更新:2016-11-30 10:04:28

  上一篇:go MQTT 客戶端收發 MQTT 消息__Java 接入示例_MQTT 接入(物聯)_消息隊列 MQ-阿裏雲
  下一篇:go MQTT iOS 接入示例__iOS 接入示例_MQTT 接入(物聯)_消息隊列 MQ-阿裏雲