因为工作中遇到了需要通过权限进行mqtt消息的限制的情境,对mqtt鉴权的实现进行了简单的研究。
首先要理解mqtt的鉴权,其实是需要三个方面的控制:
- 创建链接的权限,若无此权限,客户端连创建连接的机会都没有
- 订阅一个主题的权限,当有用了链接权限,用户可以随意订阅任意主题,这达不到隔离的效果,我们还要对用户能订阅的主题进行限制
- 向一个主题发布的权限,同理我们也需要限制用户发送消息的功能
1. mosquito mqtt-broker方案
mosquito 是比较典型的mqtt服务端实现,其实也没有对其做很详细的了解,但在鉴权方案上,mosquito采用的是设置账户密码配置文件方式创建用户,并在ACLs权限列表文件进行特定的主题读写权限的定义。
通过mosquito的命令创建账户密码:
1 | # mosquitto_passwd -c /etc/mosquitto/pwd user |
根据提示设置密码后,密码文件将会生成,在设置文件.conf中:allow_anonymous
设置为否,password_file
指向密码文件后,用户生效,此时,连接mosquito服务器的mqtt连接必须携带用户和密码,才能成功创建mqtt链接。在创建连接成功后,客户端是可以随意订阅和发布所有主题的,所以mosquito还需要ACLs文件进行主题发布和订阅的控制。
ACLS文件大概格式:
1 | user user01 |
写好ACLs文件后,在设置文件.conf中添加acl_file
属性,指明ACLs为文件的路径,重启mosquito,用户的订阅和发布就被限制住了。
然而,对于完整的系统来说,mqtt不管是连接权限,还是订阅和发布权限,应该是一个动态获取并可以进行修改的,原生的mosquito鉴权固定的权限文件对于这个需求就无法胜任了,于是就有了mosquitto-auth-plugin
,这个插件可以根据一个服务器或数据库等多样化的后端提供的信息进行mosquitto权限判断。
这么说非常好,这插件用起来可不方便,因为还需要学习如何配置和编程,也就没仔细研究,也许也不是那么难,只是不喜欢。
2. mosca nodejs服务端方案
mosca 是nodejs实现mqtt服务端的首选方案,官方的文档和示例很好地展示了如何编程,提供了发送mqtt消息常用的设置比如Qos等,还能和数据库或则redis进行联动,而且还能够向mosquito一样作为standalone服务端使用,非常方便。一开始的时候自己搭建了转发服务没问题,现在需要鉴权后却发现没那么容易,找了一番没发现有人的博客或则论坛有详细讲解,终于在github的wiki中看到了Authentication & Authorization
页面。
官方是这么描述的:
使用mosca,你可以通过定义三个方法来认证一个客户端
#authenticate
#authorizePublish
#authorizeSubscribe
然后给出了一个例子(简单翻译一下)
1 | // 如果用户密码有效,则连接被许可 |
接着就是启动服务:
1 | var server = new mosca.Server(settings); |
刚开始看的时候还不太理解,这三个函数都不怎么友好,参数多,还有callback,不是那么能直接看懂。但多看几遍其实可以了解,这三个函数正是mqtt鉴权所需要的东西。可以理解成当每个函数中的callback(null,Boolean)
执行,鉴权工作就完成了,而其中的Boolean
值就是我们可以自定义的变量,是需要脑洞的地方(promise,数据库),而这时会发现三个函数的参数都是实现骚操作非常需要的。
到目前还没能直接进行测试,等有空再上来更新(应该没问题)。