为什么mosquitto 禁用了 topic “#“后,无法使用主题中包含%c client_id了?
禁用通配符主题#后无法使用%c占位符的问题,主要涉及Mosquitto的ACL权限机制与动态占位符的逻辑冲突。具体原因如下:
- 通配符与动态占位符的依赖关系
 #通配符的作用:通配符#允许订阅多级模糊匹配主题(如sensor/#可订阅所有以sensor/开头的主题)7。
 %c占位符的特性:%c用于在主题中动态替换为连接客户端的client_id(如订阅sensor/%c/data会替换为sensor/client123/data)。此功能依赖于客户端连接时动态生成主题路径的能力4。
- 通配符禁用后的权限限制
 当禁用#通配符时,ACL规则要求客户端必须明确指定完整主题路径。此时动态生成的%c占位符无法通过模糊匹配验证,因为系统要求主题必须完全静态且可预判27。
 例如:若ACL配置为禁止#,则客户端试图订阅sensor/%c/data时,Mosquitto会检查主题是否包含通配符或动态占位符,发现%c可能隐含动态匹配逻辑(即使实际生成的是静态主题),触发权限拒绝24。
- 解决方法
 需调整ACL规则以兼容动态占位符:
conf
 Copy Code
允许客户端使用自身client_id动态生成主题
pattern write sensor/%c/#
 此规则明确允许客户端在sensor/%c/路径下动态生成子主题,同时避免使用全局通配符#27。
比如:
 topic write v2/s/+/%c/status
 #topic read v2/c/%c/cmd
 这一行不行,
 改成:
 pattern write v2/s/+/%c/#
 pattern read v2/c/%c/#
 可以了。
完整的:
#topic write v2/s/+/%c/status
pattern write v2/s/+/%c/#
topic write +/+/status
#topic read v2/c/%c/cmd
pattern read v2/c/%c/#
#topic read +/cmd
pattern read %c/#
topic deny $SYS/#
#topic deny #这样实现了匿名用户根据client_id动态订阅主题。并且让“#”主题无法查看到信息。
mosquitto_sub -h mqtt.xxxx.hk -p 8883 -v -t '#'
