開啟emqx用户驗證後的SpringBoot下MQTT一次踩坑記錄

語言: CN / TW / HK

背景

測試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的一些常用端口號瞭解多一些,剛開始就不會認為是端口號的問題了,多走了兩步彎路,以後要注意。