1. EMQX Broker用户认证概述
EMQX作为一款高性能的MQTT消息中间件,用户认证是其安全体系的第一道防线。在实际物联网项目中,我曾遇到过因认证配置不当导致设备被恶意控制的案例:某智能家居平台由于使用默认密码,被攻击者批量连接后发送非法控制指令。这让我深刻认识到正确配置认证的重要性。
认证机制本质上解决的是"你是谁"的问题。当客户端连接EMQX时,Broker会通过CONNECT报文中的用户名/密码或客户端ID进行身份核验。与授权(解决"你能做什么")不同,认证只判断连接合法性。EMQX 5.x版本支持多种认证方式:
- 内置数据库认证
- MySQL/PostgreSQL等外部数据库
- Redis认证
- MongoDB认证
- HTTP API认证
- JWT认证
关键提示:生产环境务必避免使用明文密码。我曾在安全审计中发现,有团队将密码直接写在配置文件中,这相当于把钥匙挂在门锁上。
2. 认证方式选型与配置
2.1 内置数据库认证配置
这是最快速的入门方式,适合测试环境或小型部署。通过EMQX Dashboard配置的步骤如下:
- 登录Dashboard(默认地址http://localhost:18083)
- 左侧菜单选择"认证" → "认证方式"
- 点击"创建"选择"Password-Based"
- 认证类型选择"Built-in Database"
- 设置密码加密方式(推荐sha256或bcrypt)
- 点击"确定"保存配置
通过REST API添加用户的示例:
bash复制curl -X POST -u admin:public http://localhost:8081/api/v5/authentication/password_based:built_in_database/users \
-H "Content-Type: application/json" \
-d '{"user_id":"device001","password":"s3cr3t"}'
踩坑记录:内置数据库用户信息存储在内存中,集群环境下需要确保所有节点同步。有次线上故障就是因为新增用户未同步到全部节点,导致设备间歇性认证失败。
2.2 MySQL外部认证实战
对于中大型项目,我推荐使用外部数据库。以MySQL为例的配置过程:
- 准备MySQL表结构:
sql复制CREATE TABLE `mqtt_users` (
`username` varchar(100) NOT NULL,
`password_hash` varchar(100) NOT NULL,
`salt` varchar(40) DEFAULT NULL,
`created` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`username`)
) ENGINE=InnoDB;
- 插入测试数据(使用SHA256加盐):
sql复制INSERT INTO mqtt_users VALUES (
'test_client',
'8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918',
'random_salt',
NOW()
);
- EMQX配置关键参数:
properties复制# etc/plugins/emqx_auth_mysql.conf
auth.mysql.server = "127.0.0.1:3306"
auth.mysql.username = "emqx"
auth.mysql.password = "password"
auth.mysql.database = "mqtt"
auth.mysql.password_hash = "sha256"
auth.mysql.auth_query = "SELECT password_hash AS password, salt FROM mqtt_users WHERE username = '%u'"
- 重启插件:
bash复制./bin/emqx_ctl plugins reload emqx_auth_mysql
性能优化建议:
- 为username字段建立索引
- 使用连接池(配置pool_size参数)
- 定期清理不活跃用户
3. 高级认证方案
3.1 JWT认证集成
在微服务架构中,JWT是理想的认证方案。配置要点:
- 生成JWT密钥对:
bash复制openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -pubout -out public.pem
- EMQX配置:
properties复制# etc/plugins/emqx_auth_jwt.conf
auth.jwt.secret = file:///path/to/public.pem
auth.jwt.from = password # 从password字段读取JWT
auth.jwt.verify_claims = on
auth.jwt.verify_claims.username = %u # 验证用户名声明
- 客户端连接示例(Node.js):
javascript复制const jwt = require('jsonwebtoken');
const privateKey = fs.readFileSync('private.pem');
const token = jwt.sign({
username: 'client123',
exp: Math.floor(Date.now()/1000) + 3600
}, privateKey, { algorithm: 'RS256' });
const client = mqtt.connect('mqtt://localhost', {
username: 'client123',
password: token
});
3.2 HTTP Webhook认证
对于已有用户系统的场景,HTTP认证提供了最大灵活性。典型配置:
properties复制# etc/plugins/emqx_auth_http.conf
auth.http.auth_req = "http://127.0.0.1:8080/mqtt/auth"
auth.http.auth_req.method = post
auth.http.auth_req.params = "clientid=%c,username=%u,password=%P"
认证服务示例(Python Flask):
python复制@app.route('/mqtt/auth', methods=['POST'])
def auth():
data = request.form
# 实际项目中应查询数据库
if data['username'] == 'admin' and data['password'] == 'admin123':
return jsonify({"result": "allow"})
return jsonify({"result": "deny"})
性能提示:HTTP认证会增加连接延迟,建议:
- 启用Keep-Alive
- 实现缓存机制
- 考虑使用gRPC替代REST API
4. 安全加固与故障排查
4.1 密码安全策略
- 强制密码复杂度(EMQX企业版功能):
properties复制# etc/plugins/emqx_auth_mysql.conf
auth.mysql.password_hash = "bcrypt"
auth.mysql.password_hash_rounds = 10
auth.mysql.password_regex = "^[A-Za-z0-9]{8,}$"
- 定期轮换方案:
- 使用JWT设置较短有效期
- 通过HTTP认证集成现有IAM系统
- 实现定期强制修改密码逻辑
4.2 常见故障诊断
- 认证失败排查流程:
code复制检查EMQX日志(/log/emqx.log.1)
↓
确认插件已启用(./bin/emqx_ctl plugins list)
↓
测试数据库连接(mysql -u emqx -p)
↓
验证查询语句(EXPLAIN SELECT...)
↓
检查密码哈希算法是否匹配
- 典型错误及解决:
- "Plugin load error: emqx_auth_mysql"
→ 检查依赖库:yum install -y mysql-devel - "Client authentication failed"
→ 对比密码哈希值:echo -n "password+salt" | sha256sum - "Auth timeout"
→ 调整超时设置:auth.mysql.query_timeout = 5s
4.3 监控与审计
- 关键监控指标:
- 认证成功率(emqx_authentication_success_total)
- 认证延迟(emqx_authentication_time)
- 失败原因统计(emqx_authentication_failure_reason)
- 审计日志配置:
properties复制# etc/emqx.conf
log.auth.success = notice
log.auth.failure = warning
- 我常用的监控命令:
bash复制# 实时查看认证日志
tail -f /var/log/emqx/emqx.log | grep -E "auth|authentication"
# 统计认证失败IP
grep "authentication failed" /var/log/emqx/emqx.log.1 | awk '{print $7}' | sort | uniq -c
5. 性能优化实践
5.1 认证缓存配置
EMQX默认启用认证缓存,建议调整参数:
properties复制# etc/emqx.conf
auth.cache.enable = true
auth.cache.max_size = 102400 # 缓存10万条记录
auth.cache.ttl = 15m # 适合频繁重连场景
缓存命中率检查:
bash复制./bin/emqx_ctl metrics | grep auth_cache
5.2 集群部署建议
- 认证数据同步策略:
- 内置数据库:使用emqx_ctl data export/import
- 外部数据库:配置主从复制
- Redis:使用集群模式
- 我遇到过的集群问题:
- MySQL单点故障 → 改用MySQL Group Replication
- Redis缓存不一致 → 增加cluster-node-timeout
- 跨地域延迟 → 部署地域就近的认证副本
5.3 压力测试数据
使用mqtt-benchmark工具测试不同认证方式的性能表现(单节点8核16G):
| 认证方式 | 连接速率(conn/s) | 平均延迟(ms) | CPU占用 |
|---|---|---|---|
| 内置数据库 | 12,000 | 8 | 45% |
| MySQL | 7,500 | 15 | 60% |
| Redis | 9,800 | 11 | 55% |
| HTTP API | 3,200 | 35 | 70% |
优化建议:
- 超过5000连接/秒时考虑分片部署
- HTTP认证建议使用高性能框架(如Go)
- 启用TCP快速打开(tcp_fastopen=3)
