一、完整流程示例(含代码和配置)

1. 环境准备
  • ​EMQ X 版本​:5.x(支持 MySQL 插件)
  • ​MySQL 版本​:5.7+(推荐 8.0)
  • ​工具​:MySQL 客户端、MQTT 客户端(如 MQTTX 或 Mosquitto)

2. 创建 MySQL 数据库和表

-- 创建数据库
CREATE DATABASE IF NOT EXISTS mqtt_auth;
USE mqtt_auth;

-- 创建用户表(关键字段)
CREATE TABLE mqtt_user (
  id INT AUTO_INCREMENT PRIMARY KEY,
  username VARCHAR(100) NOT NULL UNIQUE,  -- 用户名(唯一)
  password_hash VARCHAR(255) NOT NULL,     -- 加密后的密码
  salt VARCHAR(35) DEFAULT NULL,           -- 盐值(用于加密)
  is_superuser TINYINT DEFAULT 0           -- 是否超级用户(跳过 ACL)
);

-- 插入测试用户(密码为 `test123`,盐值 `salt_abc`)
-- 使用 SHA256 加密(盐值拼接在密码前)
INSERT INTO mqtt_user (username, password_hash, salt)
VALUES (
  'device_001',
  SHA2(CONCAT('salt_abc', 'test123'), 256),  -- 生成密文
  'salt_abc'
);

3. 配置 EMQX MySQL 插件

修改 etc/plugins/emqx_auth_mysql.conf:


## 数据库连接配置
auth.mysql.server = 127.0.0.1:3306
auth.mysql.username = root
auth.mysql.password = root_password
auth.mysql.database = mqtt_auth

## 认证查询语句(关键!)
auth.mysql.auth_query = SELECT password_hash AS password, salt FROM mqtt_user WHERE username = '%u' LIMIT 1

## 加密方式(必须与数据库生成方式一致)
auth.mysql.password_hash = sha256,salt  # 盐值前缀 + SHA256

4. 启用插件并测试
# 重启插件
./bin/emqx_ctl plugins reload emqx_auth_mysql

# 关闭匿名认证(etc/emqx.conf)
allow_anonymous = false

5. 客户端连接测试

使用 ​MQTTX​ 或 ​Mosquitto​ 工具:


# 连接命令(密码为明文 `test123`)
mosquitto_sub -h 127.0.0.1 -p 1883 \
  -u device_001 -P test123 \
  -t 'test/topic' -d

二、关键问题解析

1. ​密码加密逻辑​
  • ​盐值(Salt)​​:随机字符串,用于防止彩虹表攻击。
  • ​加密方式​:
    • sha256,salt:SHA256(盐值 + 密码) → 存储到 password_hash。
    • md5,salt:MD5(盐值 + 密码)。
  • ​验证流程​:
    EMQX 用配置的加密方式对客户端输入的密码 + 盐值加密,与数据库中的 password_hash 比对。
2. ​ACL 权限控制(可选)​​

创建 mqtt_acl 表控制主题访问:


CREATE TABLE mqtt_acl (
  id INT AUTO_INCREMENT PRIMARY KEY,
  username VARCHAR(100),
  clientid VARCHAR(100),
  topic VARCHAR(255) NOT NULL,
  access INT CHECK (access IN (1,2,3)),  -- 1=订阅, 2=发布, 3=全部
  action INT CHECK (action IN (1,2))      -- 1=允许, 2=拒绝
);

-- 示例:允许 device_001 订阅 `test/#`
INSERT INTO mqtt_acl (username, topic, access, action)
VALUES ('device_001', 'test/#', 1, 3);

三、查看详细日志

这是最直接有效的排查方法。通过日志可以明确看到认证失败的具体原因。


# 开启调试日志并实时查看
./bin/emqx_ctl log set-level debug
tail -f log/emqx.log | grep -E "auth_mysql|superuser|device_001"

更多推荐