news 2026/9/23 15:08:57

EMQX Redis 授权兼容模式 v4 深度解析:无缝承接 EMQX 4.x ACL 数据

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
EMQX Redis 授权兼容模式 v4 深度解析:无缝承接 EMQX 4.x ACL 数据

EMQX Redis 授权兼容模式 v4 深度解析:无缝承接 EMQX 4.x ACL 数据

【免费下载链接】emqxThe most scalable and reliable MQTT broker for AI, IoT, IIoT and connected vehicles项目地址: https://gitcode.com/gh_mirrors/em/emqx

EMQX 5.x 的 Redis 授权(Authorization)新增了compatibility_mode = v4配置项,用于兼容 EMQX 4.x 时代写入 Redis 的旧版 ACL 数据。本文以本仓库中对应变更文档 changes/ee/fix-16730.en.md 为核心,结合emqx_auth_redis应用的源码实现与测试用例,深入讲解该兼容模式的工作原理、配置方法、旧版占位符与 ACL 值的映射规则,以及从 EMQX 4.x 平滑迁移到 5.x 的落地要点。读完本文,你将能够准确判断是否启用该模式、正确配置 Redis 授权,并理解底层占位符渲染与规则解析的完整链路。

一、为什么需要兼容模式:EMQX 4.x 与 5.x 的 ACL 数据格式差异

在 EMQX 4.x 时代,Redis 中存储的 ACL(访问控制列表)数据采用了与 5.x 截然不同的两种约定:

  1. 占位符语法不同:4.x 使用%u(用户名)和%c(客户端 ID)作为占位符,例如查询命令HGETALL mqtt_acl:%u、主题过滤器pub/%usub/%c;而 5.x 使用${username}${clientid}这类模板变量语法。
  2. 访问值编码不同:4.x 的规则值使用数字123分别表示 subscribe(订阅)、publish(发布)和 all(全部);而 5.x 原生接受字符串subscribepublishall,以及包含actionqosretain等字段的 JSON 对象。

如果直接沿用 4.x 的 Redis 数据,5.x 的 Redis 授权会因无法解析这些旧格式而拒绝匹配,导致客户端全部被拒(或依赖no_match的兜底策略)。兼容模式正是为了解决这一迁移痛点而生。

二、compatibility_mode 配置项:定义、取值与默认行为

该配置项在 emqx_authz_redis_schema.erl 中定义,属于 Redis 授权数据源的专属字段:

compatibility_mode() -> ?HOCON(hoconsc:enum([disabled, v4]), #{ required => false, default => disabled, desc => ?DESC(compatibility_mode), example => v4 }).

关键信息如下:

属性取值说明
枚举值disabled/v4仅支持这两个取值
默认值disabled默认关闭,保证已有 Redis 授权行为完全不变
是否必填不配置即视为disabled

i18n 描述文件 emqx_authz_redis_schema.hocon 中给出了官方语义:

Redis ACL compatibility mode. Set tov4to accept legacy ACL values1|2|3and placeholders%u/%c.

配置方式(HOCON 格式,位于authorization.sources下):

authorization { sources = [ { type = redis enable = true redis_type = single server = "127.0.0.1:6379" database = 1 password = "public" cmd = "HGETALL mqtt_acl:%u" compatibility_mode = v4 } ] }

说明:测试代码 emqx_authz_redis_SUITE.erl 中的raw_redis_authz_config/0提供了最小可用配置骨架(type=redisredis_type=singlecmd等),可作为手工编写配置时的参照。该配置同样支持redis_sentinelredis_cluster两种部署形态,对应redis_type = sentinel / cluster

三、兼容模式下的两大核心行为

3.1 旧版占位符 %u/%c 的自动转换

启用compatibility_mode = v4后,cmd命令模板与查询返回的主题过滤器中的%u%c会被自动转换为 5.x 的模板变量语法${username}${clientid}。这一逻辑由 emqx_authz_redis.erl 中的normalize_legacy_placeholders/2实现:

normalize_legacy_placeholders(Bin, ?ACL_COMPAT_MODE_V4) when is_binary(Bin) -> binary:replace( binary:replace(Bin, <<"%u">>, <<"${username}">>, [global]), <<"%c">>, <<"${clientid}">>, [global] ); normalize_legacy_placeholders(Value, _ACLCompatibilityMode) -> Value.

从源码可以看到两个关键细节:

  • 替换是全局的([global]:同一字符串中出现的所有%u/%c都会被替换,且先替换%u再替换%c
  • 仅在 v4 模式下生效:其他任何取值都原样返回,不会做任何转换。

该函数被调用在两个位置:

  1. new_state/2初始化状态时,对cmd模板字符串做归一化,再进入parse_cmd/1的模板解析流程;
  2. do_authorize/5中处理每条返回记录时,对哈希表的 key(即主题过滤器)做归一化。

也就是说,占位符转换同时作用于查询命令和查询结果中的主题过滤器。例如 4.x 的HGETALL mqtt_acl:%u在 v4 模式下等效于 5.x 的HGETALL mqtt_acl:${username},而存储为pub/%u的主题过滤器会被当作pub/${username}参与匹配。

3.2 旧版 ACL 访问值 1|2|3 的映射

启用 v4 模式后,查询结果中的规则值123会被映射为订阅、发布、全部三种动作。该逻辑位于parse_rule/2

parse_rule(<<"1">>, ?ACL_COMPAT_MODE_V4) -> {ok, #{<<"action">> => <<"subscribe">>}}; parse_rule(<<"2">>, ?ACL_COMPAT_MODE_V4) -> {ok, #{<<"action">> => <<"publish">>}}; parse_rule(<<"3">>, ?ACL_COMPAT_MODE_V4) -> {ok, #{<<"action">> => <<"all">>}}; parse_rule(<<"publish">>, _ACLCompatibilityMode) -> {ok, #{<<"action">> => <<"publish">>}}; parse_rule(<<"subscribe">>, _ACLCompatibilityMode) -> {ok, #{<<"action">> => <<"subscribe">>}}; parse_rule(<<"all">>, _ACLCompatibilityMode) -> {ok, #{<<"action">> => <<"all">>}};

映射关系总结如下:

Redis 中存储的规则值兼容模式(v4)下的含义5.x 原生等价写法
1subscribe(订阅)subscribe
2publish(发布)publish
3all(全部)all

继续往下读源码还可以看到,除数字与字符串外,parse_rule/2还支持 JSON 对象形式(如{"action":"publish","qos":1,"retain":true}),这部分在 v4 与非 v4 模式下行为一致。若返回的值既不是1|2|3、也不是publish/subscribe/all、更不是合法 JSON 对象,则会被判定为非法规则并记录错误日志(parse_rule_error),该条规则按不匹配处理。

四、完整工作链路:从配置到鉴权决策

为了看清兼容模式在整条授权链路中的位置,这里梳理 emqx_authz_redis.erl 的关键调用关系:

  1. 资源生命周期回调create/1update/2destroy/1负责创建/更新/销毁 Redis 连接资源;其中new_state/2会读取compatibility_mode并通过normalize_acl_compatibility_mode/1归一化取值(<<"v4">>v4原子都识别为 v4,其余一律视为disabled),随后对cmd做占位符归一化与模板解析。
  2. 授权回调authorize/4:首先用emqx_auth_template:render_deep_for_raw/2基于当前连接上下文(用户名、客户端 ID 等)渲染出最终 Redis 命令,再通过emqx_authz_utils:cached_simple_sync_query/3走缓存查询;查询失败时记录错误日志并按后端失败策略(取决于安全配置档)返回结果。
  3. 规则匹配do_authorize/5:对查询返回的每一对<主题过滤器, 规则值>调用parse_rule/2解析,构造出带permission=allow的规则映射,最终交给emqx_authz_utils:authorize_with_row/6完成与目标 Topic 的匹配,命中则返回{matched, Permission},否则继续遍历下一条。

另外值得注意的是validate_cmd/1对命令的约束:Redis 授权仅接受HGETALLHMGET两种命令,且命令不能为空。这是 Redis 作为授权数据源时查询形态的硬性限制,配置cmd时需遵守。

五、测试用例如何验证兼容行为

兼容模式的正确性在 emqx_authz_redis_SUITE.erl 中有三组针对性用例,可直接作为行为规格阅读:

1.v4_acl_values(数字值映射)

预先写入HMSET acl:username a 1 b 2 d 3cmdHGETALL acl:${username}compatibility_mode => v4。校验结果:

  • 主题a:发布 deny、订阅 allow(1→ subscribe)
  • 主题b:发布 allow、订阅 deny(2→ publish)
  • 主题d:发布 allow、订阅 allow(3→ all)

2.v4_placeholders_in_cmd_and_topic_filter(占位符转换)

预先写入HMSET mqtt_acl:username pub/%u 2 sub/%c 1cmdHGETALL mqtt_acl:%ucompatibility_mode => v4。校验结果:

  • 客户端以username连接时,允许向pub/username发布(命令中的%u被替换,返回的主题过滤器pub/%u也被解析为pub/${username});
  • 允许订阅sub/clientid%c同理转换为${clientid})。

3.v4_acl_values_ignored_without_compat(默认模式行为不变)

同样的1|2|3数据,但不设置compatibility_mode。校验结果为所有主题的发布、订阅请求全部 deny——即未启用兼容模式时,1|2|3会被当作非法规则忽略,原有行为完全不受影响。这正是"默认保持禁用,现有 Redis 授权行为不变"这一设计承诺的直接证据。

六、迁移实践与注意事项

结合变更文档、源码与测试,从 EMQX 4.x 迁移到 5.x 时可参考以下要点:

  1. 确认数据格式:检查 Redis 中 ACL 数据的命令模板是否使用了%u/%c占位符,规则值是否为1|2|3。只要命中其中一种,就需要考虑启用兼容模式。
  2. 启用方式:在authorization.sources的 redis 数据源中设置compatibility_mode = v4并保留原cmd(如HGETALL mqtt_acl:%u),无需改写 Redis 数据本身即可让旧数据重新生效。
  3. 兼容性影响面:v4 模式会同时改变cmd模板与查询结果主题过滤器的占位符解析,因此务必在启用后回归验证:旧的%u数据是否会与使用${username}的新数据混用(两者在 v4 模式下等价,可共存)。
  4. 命令约束:无论是否启用兼容模式,cmd只能是HGETALLHMGET;自定义命令会导致数据源创建或更新失败。
  5. 安全兜底:若旧 ACL 数据中存在非法规则值(如拼写错误的pub),该条规则会被跳过并打印parse_rule_error日志,最终是否放行取决于no_match与安全配置档(legacy/hardened)的设定,建议迁移前先在小范围灰度验证。

七、相关文件索引

  • 变更文档:changes/ee/fix-16730.en.md,并收录于 changes/6.1.1.en.md 的 Access Control 章节
  • 配置 schema 定义:emqx_authz_redis_schema.erl
  • 核心实现(占位符转换、规则解析、授权回调):emqx_authz_redis.erl
  • 行为验证测试:emqx_authz_redis_SUITE.erl
  • 配置项语义描述:emqx_authz_redis_schema.hocon

【免费下载链接】emqxThe most scalable and reliable MQTT broker for AI, IoT, IIoT and connected vehicles项目地址: https://gitcode.com/gh_mirrors/em/emqx

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/23 15:05:29

2024 CCPC网络赛题目工程化复用指南

简介&#xff1a;本资源为2024年中国大学生程序设计竞赛&#xff08;CCPC&#xff09;网络赛官方题目PDF&#xff0c;面向ACM/ICPC及算法竞赛参赛者、高校算法课程学习者与算法教练。题目A「军军军训训训 I」聚焦队列状态演化建模&#xff0c;需结合图论与组合数学分析nm方阵在…

作者头像 李华
网站建设 2026/9/23 15:02:39

Python PIL文件占用问题解析与解决方案

1. 问题现象与背景分析最近在做一个图片批量处理脚本时&#xff0c;遇到了一个看似简单却困扰了我半天的问题&#xff1a;用Python的PIL库打开图片后&#xff0c;直接对文件进行重命名操作时&#xff0c;系统报出"Permission denied"的错误。这个情况在Windows和Linu…

作者头像 李华
网站建设 2026/9/23 14:55:55

Java房屋租赁管理系统源码部署与二次开发实战指南

简介&#xff1a;这份资源是面向Java Web初学者与进阶开发者的房屋租赁管理系统完整源码包&#xff0c;适合用于课程设计、毕业设计或自学练手。系统围绕房源信息、租户资料、租赁合同、租金收取、费用计算与到期提醒等业务模块展开&#xff0c;帮助理解Java在实际管理类项目中…

作者头像 李华
网站建设 2026/9/23 14:50:47

电商后台系统怎么做?零代码搭建经营看板的完整指南(2026最新)

摘要&#xff1a;电商后台系统越做越重&#xff0c;问题往往不在功能多少&#xff0c;而在数据有没有被用起来。本文结合2026年最新实践&#xff0c;讲清如何用零代码把后台数据变成经营看板&#xff0c;减少重复劳动、更快做决策。 很多老板跟我聊后台的时候&#xff0c;都会…

作者头像 李华