开启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的一些常用端口号了解多一些,刚开始就不会认为是端口号的问题了,多走了两步弯路,以后要注意。