開啟emqx使用者驗證後的SpringBoot下MQTT一次踩坑記錄
背景
測試demo安裝emqx時,首先考慮的功能性測試,並沒有考慮太多的安全性需求,因此,emqx開啟的是匿名方式,現在要上生產環境,需要採用使用者認證的方式。
現象
emqx按照原先的方式部署,開啟了匿名校驗,設定了使用者認證方式,emqx管理介面plugins中也開啟了使用者認證外掛,但是重新啟動平臺時,一直報錯:mqtt user authorization is refused the collection,即使用者無權連線,但是使用MQTT客戶端連線認證成功,可以連線上,於是乎問題有點盤旋了。
解決方式
1、防火牆開放所有有關MQTT連線的埠
問題出現的第一反應是客戶端連線不到認證伺服器,於是伺服器上將所有有關mqtt連線的埠全部開放出來,重啟了平臺,但是問題依然在。
2、程式碼排查
思考路線:
(1)MQTT客戶端可以連線,但是平臺連線認證不通過,同樣請求的是1883的埠,那麼說明1883本身埠沒有問題;
(2)那麼問題可能出現在程式碼使用者認證上,檢查了一下SpringBoot中的yaml檔案,有關mqtt的配置,發現是正確的;
(3)那麼就有一種可能,在請求1883埠時,使用者認證資訊並沒有正確攜帶
(4)於是乎找到問題本源了 查看了程式碼建立mqtt連線的方法,只是使用了url和主題,而使用者資訊並沒有正確建立,於是定位到問題本源了
(5)解決問題
`````` public MqttConnectOptions getMqttConnectOptions() { MqttConnectOptions options = new MqttConnectOptions(); options.setUserName(username); options.setPassword(password.toCharArray()); options.setServerURIs(new String[]{url}); options.setConnectionTimeout(completionTimeout); return options; }
@Bean public MqttPahoClientFactory mqttClientFactory() { DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory(); factory.setConnectionOptions(getMqttConnectOptions()); return factory; }
@Bean public MessageProducerSupport mqttInbound() { MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter(clientId,mqttClientFactory(), topic); adapter.setCompletionTimeout(completionTimeout); adapter.setConverter(new DefaultPahoMessageConverter()); adapter.setQos(1); adapter.setOutputChannel(new DirectChannel()); return adapter; } `````` 上面便是修改後的關鍵程式碼,主要是在將使用者資訊填充到連線屬性中,並利用工廠模式建立了一個通道介面卡,這樣程式啟動時便會初始化這些bean,實現與MQTT伺服器的連線並監聽配置進去的主題。
至此這個填坑過程完成。
總結
排查問題看日誌很重要,但是學會正確的分析日誌檔案也是需要經驗以及正確思路分析的,如果對MQTT的一些常用埠號瞭解多一些,剛開始就不會認為是埠號的問題了,多走了兩步彎路,以後要注意。