2.《一个物联网系统的实现》之 EMQX 配置
0.前言
物联网系统中想要实现用户控制设备(比如开关打开)、用户获取设备状态(比如获取温度信息),就需要用户和设备之间可以相互发送数据。这里博主选择MQTT
协议提供用户和设备之间的交互能力。
EMQX
开源版:全球下载量超千万的开源物联网 MQTT
服务器,高效可靠连接海量物联网设备,高性能实时处理消息与事件流数据,可运行在公有云、私有云和混合云上。巴拉巴拉。。。(这段从EMQX
官网抄的😮💨,总之是个MQTT
服务器)
1.EMQX 基础配置
1.1关闭匿名登录
EMQX
安装后默认允许匿名登陆,用户使用任意的账号密码,都可以登陆成功,为了安全起见,这里我们关闭匿名登陆。
修改/etc/emqx/emqx.config
配置文件下allow_anonymous = false
即可关闭匿名登录。
1.2配置MySQL服务器
EMQX
支持使用MySQL
作为用户身份验证,和信息发布权限认证。所谓身份认证就是使用MySQL
里的某个表或几个表保存用户的账号和密码,当用户发起一个MQTT
连接时通过表里的信息验证用户身份。因为MQTT
协议是基于某个主题订阅
和发布
信息的,订阅了同一个主题的MQTT
客户端都可以接收到向着个主题发布的消息。所谓信息发布权限认证就是控制MQTT
客户端,可以订阅哪些主题,可以向哪些主题发布消息。
- 首先创建一个MySQL的数据库,这里我使用bt宝塔面板创建。
- 在数据库中创建一个用户表
CREATE TABLE `mqtt_user` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(100) DEFAULT NULL,
`password` varchar(100) DEFAULT NULL,
`salt` varchar(35) DEFAULT NULL,
`is_superuser` tinyint(1) DEFAULT 0,
`created` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `mqtt_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
- 向用户表中插入一个用户
INSERT INTO `mqtt_user` ( `username`, `password`, `salt`)
VALUES ('emqx', '123456', NULL);
- 创建一个订阅/发布授权表
CREATE TABLE `mqtt_acl` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`allow` int(1) DEFAULT 1 COMMENT '0: deny, 1: allow',
`ipaddr` varchar(60) DEFAULT NULL COMMENT 'IpAddress',
`username` varchar(100) DEFAULT NULL COMMENT 'Username',
`clientid` varchar(100) DEFAULT NULL COMMENT 'ClientId',
`access` int(2) NOT NULL COMMENT '1: subscribe, 2: publish, 3: pubsub',
`topic` varchar(100) NOT NULL DEFAULT '' COMMENT 'Topic Filter',
PRIMARY KEY (`id`),
INDEX (ipaddr),
INDEX (username),
INDEX (clientid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
以下为订阅/发布授权表的表字段说明
allow:禁止(0),允许(1)
ipaddr:设置 IP 地址
username:连接客户端的用户名,此处的值如果设置为 $all 表示该规则适用于所有的用户
clientid:连接客户端的 Client ID
access:允许的操作:订阅(1),发布(2),订阅发布都可以(3)
topic:控制的主题,可以使用通配符,并且可以在主题中加入占位符来匹配客户端信息,例如 t/%c 则在匹配时主题将会替换为当前客户端的
Client ID
%u:用户名
%c:Client ID
- 向发布授权表插入规则
-- 禁止所有MQTT客户端订阅发布所有主题
INSERT INTO mqtt_acl (allow, ipaddr, username, clientid, access, topic) VALUES (0, NULL, '$all', NULL, 3, '#');
-- 允许客户端订阅发布"/mqtt/用户名"的主题,对应上面创建的emqx用户,他可以订阅"/mqtt/emqx"主题,也可以向"/mqtt/emqx"主题发布数据
INSERT INTO mqtt_acl (allow, ipaddr, username, clientid, access, topic) VALUES (1, NULL, '$all', NULL, 3, '/mqtt/%u');
1.3配置emqx_auth_mysql 插件
修改/etc/emqx/plugins/emqx_auth_mysql.conf
配置emqx_auth_mysql
插件。
可以参考我的配置
auth.mysql.server = 127.0.0.1:3306
auth.mysql.pool = 8
auth.mysql.username = iot
auth.mysql.password = wScYEmWKZJ8TGa4m
auth.mysql.database = iot
auth.mysql.query_timeout = 5s
auth.mysql.auth_query = select password from mqtt_user where username = '%u' limit 1
auth.mysql.password_hash = plain
auth.mysql.super_query = select is_superuser from mqtt_user where username = '%u' limit 1
auth.mysql.acl_query = select allow, ipaddr, username, clientid, access, topic from mqtt_acl where ipaddr = '%a' or username = '%u' or username = '$all' or clientid = '%c'
auth.mysql.ssl = off
保存配置文件后重启EMQX
使设置生效
stdio emqx restart
进入EMQX
后台,启动emqx_auth_mysql
插件
2.EMQX SSL 配置
博主参考官方的文档,配置EMQX 的SSL加密始终不成功,所以博主换了种通过nginx
反向代理的EMQX
的WebSocket
接口实现SSL加密。此处为官方的SSL配置文档,大家也可以试试。
博主使用的bt宝塔面板,做web管理。
2.1 创建一个网站
- 点击设置
- 添加反向代理
- 修改反向代理配置文件使支持WebScoket
#持久化连接配置
proxy_connect_timeout 30s;
proxy_read_timeout 86400s;
proxy_send_timeout 30s;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
- 添加SSL证书,点击未部署
- 填入
key
和证书
,保存后开启强制HTTPS
。key
和证书
博主使用的是在阿里云免费申请的,这里就不再赘述了。传送门(PS:在选购SSL证书
->DV单域名证书【免费试用】
中)
3.测试
使用的测试工具
- 连接
MQTT
服务器
- 订阅主题
/mqtt/emqx
- 向主题
/mqtt/emqx
发布消息,可以看到成功发布并接收到了/mqtt/emqx
主题的消息
以上
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。