Emqtt -- 05 -- Mysql插件认证及访问控制
现在我们来解析下Mysql插件认证以及访问控制,默认关闭了匿名认证
一、创建用户表和控制表
根据官方文档,用户表的名称为:mqtt_user,访问控制表的名称为:mqtt_acl
-
mqtt_user
CREATE TABLE mqtt_user ( id int(11) unsigned NOT NULL AUTO_INCREMENT, username varchar(8) DEFAULT NULL COMMENT 'mqtt用户名', password varchar(12) DEFAULT NULL COMMENT 'mqtt密码', salt varchar(20) DEFAULT NULL COMMENT '加盐随机变量', is_superuser tinyint(1) DEFAULT 0 COMMENT '是否为超级用户: 0=否1=是', create_time datetime DEFAULT NULL COMMENT '创建时间', modify_time datetime DEFAULT NULL COMMENT '修改时间', PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='mqtt用户表';
-
mqtt_acl
CREATE TABLE tbl_mqtt_acl ( id int(11) unsigned NOT NULL AUTO_INCREMENT, allow int(1) DEFAULT NULL COMMENT '是否允许连接: 0=拒绝1=允许', ipaddr varchar(60) DEFAULT NULL COMMENT 'mqtt客户端IP地址', username varchar(8) NOT NULL COMMENT 'mqtt用户名', clientid varchar(100) DEFAULT NULL COMMENT 'clientId', access int(2) NOT NULL COMMENT '行为类型: 1=订阅2=发布3=订阅+发布', topic varchar(100) NOT NULL DEFAULT '' COMMENT '主题', create_time datetime DEFAULT NULL COMMENT '创建时间', modify_time datetime DEFAULT NULL COMMENT '修改时间', PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='mqtt权限控制表';
二、配置mysql认证
在etc/plugins目录下修改 emq_auth_mysql.conf 配置文件
-
cd /usr/local/emqtt/emqttd/etc/plugins
-
vim emq_auth_mysql.conf
-
添加数据库连接配置,保存并退出
## MySQL server address. ## ## Value: Port | IP:Port ## ## Examples: 3306, 127.0.0.1:3306, localhost:3306 auth.mysql.server = 127.0.0.1:3306 ## MySQL pool size. ## ## Value: Number auth.mysql.pool = 8 ## MySQL username. ## ## Value: String auth.mysql.username = root ## MySQL password. ## ## Value: String auth.mysql.password = root ## MySQL database. ## ## Value: String auth.mysql.database = mqtt
-
开启mysql认证插件
-
第一种方式:emqttd_ctl plugins load emq_auth_mysql
-
第二种方式:在web管理控制台中开启该插件
-
-
重启服务,使插件生效
三、测试
emqtt的mysql插件默认开启 sha256 加密,其他加密方式如下图,其中 plain 表示明文不加密
-
此时我在数据库中配置了
-
username:admin
-
password:8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92 (123456)
-
-
在项目中配置了
-
username:admin
-
password:123456
-
clientid: mqtt-client
-
topic: MQTT
-
-
此时我们再启动项目时,只有正确地配置了用户名和密码之后,才可以连接成功,否则会报异常
(当项目启动连接到emqtt服务时,emqtt服务会自动将项目里配置的明文密码,使用sha256进行加密,然后与数据库中存储的密文进行比较,如果相等则连接成功,如果不相等则连接失败)
四、加盐对密码进行加密
所谓加盐,就是对明文密码前面或后面加上一个随机字符串,然后再对整个字符串进行加密,增强了密码的安全性
-
cd /usr/local/emqtt/emqttd/etc/plugins
-
vim emq_auth_mysql.conf
-
修改mysql查询语句和密码加密方式,保存并退出
## Authentication query. ## ## Note that column names should be 'password' and 'salt' (if used). ## In case column names differ in your DB - please use aliases, ## e.g. "my_column_name as password". ## ## Value: SQL ## ## Variables: ## - %u: username ## - %c: clientid ## auth.mysql.auth_query = select password, salt from mqtt_user where username = '%u' limit 1 ## auth.mysql.auth_query = select password_hash as password from mqtt_user where username = '%u' limit 1 ## Password hash. ## ## Value: plain | md5 | sha | sha256 | bcrypt ## auth.mysql.password_hash = sha256 ## sha256 with salt prefix auth.mysql.password_hash = salt,sha256
-
重启服务,使配置生效
此处在 auth.mysql.auth_query 查询语句中,需要将 salt 也一并查出,并将加密方式 auth.mysql.password_hash 改为了 salt,sha256(例如:明文密码是123456,salt是admin,则将admin123456使用sha256进行加密后,把得到的密文存储到数据库中)
-
salt,sha256:表示salt在前,明文密码在后,拼接成字符串后使用sha256进行加密
-
sha256,salt:表示明文密码在前,salt在后,拼接成字符串后使用sha256进行加密
-
salt,sha256,salt:像这样明文密码前后都加salt,我试了好多次,emqtt并不支持
五、测试
-
此时我在数据库中配置了
-
username:admin
-
password:ac0e7d037817094e9e0b4441f9bae3209d67b02fa484917065f71b16109a1a78 (admin123456)
-
salt:admin
-
-
在项目中配置了
-
username:admin
-
password:123456
-
clientid: mqtt-client
-
topic: MQTT
-
-
此时我们再启动项目时,只有正确地配置了用户名和密码之后,才可以连接成功,否则会报异常
六、配置mysql权限控制
此外,我们可以对连接到emqtt的客户端进行进一步的控制 (权限控制),在这之前,我们还需要关闭默认鉴权行为
-
cd /usr/local/emqtt/emqttd/etc
-
vim emq.conf
-
找到 mqtt.acl_nomatch,将值改为 deny,保存并退出
## Default behaviour when ACL nomatch. ## ## Value: allow | deny mqtt.acl_nomatch = deny
-
cd /usr/local/emqtt/emqttd/etc/plugins
-
vim emq_auth_mysql.conf
-
修改mysql鉴权查询语句,保存并退出
## ACL query. ## ## Value: SQL ## ## Variables: ## - %a: ipaddr ## - %u: username ## - %c: clientid auth.mysql.acl_query = select allow, ipaddr, username, clientid, access, topic from mqtt_acl where username = '%u'
-
重启服务,使配置生效
此处根据自身的权限控制需求,修改 auth.mysql.acl_query 鉴权查询语句中
-
username = ‘%u’:表示当前连接到emqtt服务的用户名
-
username = ‘$all’:表示所有连接到emqtt服务的用户名
七、测试
-
此时我在数据库中配置了
-
allow:1
-
ipaddr: 本地客户端IP地址
-
username:admin
-
clientid: mqtt-client
-
access: 1
-
topic: MQTT/#
-
-
在项目中配置了
-
username:admin
-
password:123456
-
clientid: mqtt-client
-
topic: MQTT
-
-
此时我们再启动项目时,只有正确地配置了用户名、密码、clientid、topic之后 (根据鉴权查询语句来灵活配置),才可以连接成功,否则会报异常
八、启动超级用户
emqtt的mysql插件可以配置超级用户,超级用户可以跳过所有的访问控制,直接连接到emqtt服务
在数据库中直接将is_superuser字段设置为1即可
-
此时我在数据库中配置了
-
allow:1
-
ipaddr: 本地客户端IP地址
-
username:admin
-
clientid: mqtt-client
-
access: 1
-
topic: MQTT/#
-
is_superuser: 1
-
-
在项目中配置了
-
username:admin
-
password:123456
-
clientid: mqtt-client
-
topic: MQTT
-
-
此时我们再启动项目时,只要正确地配置了用户名和密码之后,就可以连接成功
例如:访问控制设置只能订阅 (access = 1),而本地服务器调用了发布 (access = 2) 的方法,因此理论上是发布不了的,而admin用户已经被设为了超级用户,所以就可以发布消息