PAYATHON 2026

ActiveMQ Artemis 如何实现按权限限制的通配符订阅?

数据阿明

结论

仅靠 Artemis 标准的 security-setting 配置,不能把 +/# 订阅自动裁剪为用户有权限的 ONE/# 和 TWO/#。要实现题目中的接收范围,更合适的做法是在同一个 MQTT 连接上分别订阅这两个 Topic Filter。

订阅授权和逐条消息过滤是不同的机制,地址权限配置不能充当通配符订阅的消息过滤器。

为什么权限不会自动缩小订阅范围?

Artemis 将 MQTT 订阅映射为绑定到对应地址的 multicast queue;consume 权限控制客户端能否消费该队列。通配符路由负责将匹配地址的消息送入队列。MQTT 映射说明、地址权限说明、通配符路由说明

仅授予 ONE/#、TWO/# 对应订阅队列的消费权限,不能让 +/# 订阅按每条消息的原始主题检查权限。

权限不足时,宽泛订阅可能在地址创建、队列创建或消费授权阶段失败。如果其他规则授予了宽泛订阅所需的权限,针对 THREE/# 的限制也不会自动过滤该订阅中的消息。

如何配置和订阅?

1. 核对 broker 使用的通配符语法

MQTT 客户端使用 /、+ 和 #。Artemis 默认的地址匹配语法使用 .、* 和 #,MQTT 协议层会进行转换。因此,使用默认 broker 语法时,broker.xml 中对应的权限匹配通常应写成:

<security-setting match="ONE.#">
    <permission type="consume" roles="user"/>
</security-setting>

<security-setting match="TWO.#">
    <permission type="consume" roles="user"/>
</security-setting>

如果已经通过 wildcard-addresses 将 broker 语法配置成 MQTT 风格,才使用 ONE/#、TWO/#。上面是消费权限片段,应合并到现有配置中。通配符语法说明

还需要确认登录用户确实映射到了 user 角色。首次建立订阅时,根据地址是否已存在以及订阅队列是否持久化,可能还需要 createAddress、createDurableQueue 或 createNonDurableQueue 权限。主动取消订阅时,也应核对相应的队列删除权限。MQTT 权限说明

2. 在同一个连接上订阅两个分支

安装 Mosquitto 客户端后,可以使用:

mosquitto_sub -h BROKER_HOST -p MQTT_PORT \
  -u user -P 'YOUR_PASSWORD' \
  -t 'ONE/#' -t 'TWO/#' -v

将主机、端口和密码替换为实际值;使用 TLS 的连接还需补充对应参数。多个 -t 可以让一个客户端订阅多个 Topic Filter。mosquitto_sub 参数说明

这两个订阅可以覆盖所需分支,无须授予 +/# 对应的宽泛访问权限。

如何确认权限边界?

使用另一个具有发布权限的客户端,分别向 ONE/test、TWO/test 和 THREE/test 发布消息。订阅端预期只收到前两个主题的消息。

随后单独尝试订阅 THREE/# 和 +/#,检查订阅确认结果与 broker 日志。仅验证当前客户端没有订阅 THREE/#,不足以证明用户无法主动访问它。还要检查用户的其他角色和兜底权限规则,确认它们没有额外授予宽泛访问权限。

如果客户端必须只提交一个 +/# 呢?

这需要额外的 broker 端或可信代理逻辑,例如将请求转换为多个已获授权的订阅。若选择在消息投递阶段过滤,还要处理持久会话、离线消息、retained messages 和权限变更等情况,不能仅靠放行订阅授权实现。

题目没有提供 Artemis 版本和完整配置,具体失败阶段及协议返回结果需要在目标环境确认。上述结论针对标准地址权限与通配符路由机制。

备注:内容仅供参考。