一、基本概念
访问控制语句逻辑上由 Access、Actions、Topics 和 Condition 4 部分组成。
| 领域 | 字段名称 | 示例值 | 必填 |
| 决策 | effect | allow/deny | 是 |
| 操作 | actions | ["connect", "pub", "sub"] | 是 |
| 资源 | topics | ["home/room1/*", "sensor/temperature/0"] | 否 |
| 条件 | clientId | "sensor*" | 否 |
| | username | "user*" | 否 |
| | qos | [0, 1, 2] | 否 |
| | retain | true/false | 否 |
| | ip | 客户端 IP 地址: 10.0.0.1 or CIDR 10.0.0.0/16 | 否 |
MQTT 实例默认提供基于数据库的策略存储源,可通过控制台或者云 API 定义、更新、排序、删除策略。策略修改变更定期同步到 MQTT 节点后生效。
三、授权链
除了内置的基于数据库的访问控制源,也支持基于 JWT claim 定义 ACL。多个授权器共同组成一个授权器链。当客户端执行操作时,按照授权器链先后进行匹配,直到获取决策结果。
每一个授权器内可定义0或多条授权策略,授权器按照定义的先后顺序,依次根据当前客户端操作(Actions)、操作资源(Topics)、以及客户端本身信息(Client ID、Username、证书信息)与策略规则进行匹配。
·当授权器的某一条策略规则匹配时,根据规则的决策,允许或者拒绝客户端操作,授权器链匹配结束。
·当策略规则不匹配时,尝试匹配该授权器内定义的下一条规则。
·当该授权器所有规则都不匹配时,交由下一个授权器进行匹配。
·当所有授权器都匹配结束仍未匹配到规则,默认拒绝客户端请求。
四、策略变量
Topic、ClientId、Username 支持以下策略变量,当授权器执行匹配操作时,会将 ${PolicyVariable} 替换成真实值后再进行匹配。
| 变量名/PolicyVariable | 语义 |
| Username | MQTT 客户端连接 Username。 |
| ClientId | MQTT Client ID。 |
| Certificate.Subject.Country | 一机一证场景下证书国家信息,详细参见 RFC4519。 |
| Certificate.Subject.Organization | 一机一证场景下证书组织信息,详细参见 RFC4519。 |
| Certificate.Subject.OrganizationalUnit | 一机一证场景下证书组织单元信息,详细参见 RFC4519。 |
| Certificate.Subject.State | 一机一证场景下证书省、直辖市信息,详细参见 RFC4519。 |
| Certificate.Subject.CommonName | 一机一证场景下证书 CommonName,详细参见 RFC4519。 |
| Certificate.Subject.SerialNumber | 一机一证场景下证书序列号,详细参见 RFC4519。 |
五、动态表达式
除了基本的策略变量替换外,数据面授权也支持使用变量表达式,对客户端变量(ClientId/Username)进行函数处理,并动态填充到 ACL 策略的 Topic、ClientId 或 Username 字段中。通过方法级别的求值,你可以从复杂的客户端标识中提取关键信息,实现更精细化的权限控制。
例如,若你的车辆 ClientId 格式为 CAR-123(“CAR”为固定前缀),你希望其只能订阅与车辆编号相关的 Topic /123/status,只需配置策略 Topic 为: /${clientId.substring(4)}/status
注意:表达式在鉴权匹配前执行,执行结果会替换原有占位符后再参与 ACL 匹配;若表达式解析失败,则对应 ACL 条件视为不匹配。
六、客户端变量
| 变量名 | 表达式写法 | 说明 |
| Client ID | ${clientId} | 客户端连接时使用的唯一标识符 |
| Username | ${username} | 客户端连接时使用的用户名 |
七、支持的字符串方法
| 常用方法 | 说明 | 示例 |
| substring(int beginIndex) | 从指定索引处开始,截取到字符串末尾。 | 输入 clientId : "WA123456"${clientId.substring(2)} 输出结果: "123456" |
| substring(int beginIndex, int endIndex) | 截取从 begin 开始到 end 结束(不包含 end)的连续字符。说明:灰度开放中,如需使用请通过工单联系我们。 | 输入 clientId : "WA123456"${clientId.substring(0, 2)} 输出结果: "WA" |
| toLowerCase() | 将字符串中所有字符转换为小写。 | 输入 clientId : "WA123456"${clientId.toLowerCase()} 输出结果: "wa123456" |
| toUpperCase() | 将字符串中所有字符转换为大写。 | 输入 clientId : "WA123456"${clientId.toUpperCase()} 输出结果: "WA123456" |
| trim() | 去除字符串首尾的空白字符(空格、制表符、换行符等)。 | 输入 clientId 字符串首尾包含空格,如:" WA123456 "${clientId.trim()} 输出结果: "WA123456" |
| tokenize(String separator) | 按指定分隔符对字符串分段,仅支持字面量分隔符(不支持正则表达式语义),分段结果保留空字段。通常与 nth() 搭配使用,单独使用时返回分段数组。说明:灰度开放中,如需使用请通过工单联系我们。 | 输入 clientId:"a..b.c"${clientId.tokenize('.')}输出结果(分段数组):["a", "", "b", "c"] |
| nth(int index) | 从 tokenize() 返回的分段数组中按下标取值。下标从 0 开始;支持负数下标,表示从末尾开始计数(-1 为最后一段)。说明:灰度开放中,如需使用请通过工单联系我们。 | 输入 clientId:"a.b.c.d"${clientId.tokenize('.').nth(-1)}输出结果:"d" |
| nthToken(String separator, int index) | tokenize + nth 的组合函数,一步完成「按分隔符分段 + 取第 N 段」,无需暴露中间分段数组,推荐优先使用。参数语义与 tokenize、nth 完全一致。说明:灰度开放中,如需使用请通过工单联系我们。 | 见下方示例 |
九、Topics 字段
Topics 字段支持下列通配符:
| 通配符/Wildcard | 语义 |
| + | 与 MQTT 协议 Topic Filter Wildcard 一致 |
| # | 与 MQTT 协议 Topic Filter Wildcard 一致 |
| ? | 任何一个字符 |
| * | 任意个字符 |
十、ClientId、Username 字段
| 通配符/Wildcard | 语义 |
| ? | 任何一个字符 |
| * | 任意个字符 |
十一、策略缓存
根据授权器的特性,MQTT 服务器可能会对策略规则进行缓存以加快获取策略速度。 因此,通过控制台或者云 API 变更的策略需要等待缓存更新后才能生效。
十二、策略顺序
策略顺序会影响授权器链的最终结果,当定义多条策略规则时,请确认授权顺序符合业务要求。
十三、限制条件
专业版最多支持配置20条授权策略,铂金版最多支持配置30条授权策略。
十五、新建策略
1. 登录 MQTT 控制台。
2. 在左侧导航栏单击资源管理 > 集群管理,选择好地域后,单击目标集群的“ID”,进入集群基本信息页面。
3. 在集群详情页,选择授权策略管理页签。默认情况下,未命中授权策略的客户端连接将被拒绝;为避免初始配置下客户端无法接入,系统已预置一条default_allow_all默认策略,表示对集群默认不进行策略管控(允许数据面的全部行为),如需要开启权限策略可以新增策略或在当前default_allow_all策略上修改。
4. 在左上角单击新建策略,填写策略信息。
| 设置项 | 说明 |
| 策略名称 | 设置策略名称。需符合命名规则:3-64个字符,支持中文、字母、数字、“-”及“_”。 |
| 描述 | 选填,不得超过128个字符。 |
| 创建方式 | 同时支持可视化的策略配置和 JSON 文件配置。 |
| 效果 | “允许” 或者 “拒绝” 二者选一,如选择 “允许”,则表示满足配置的以下条件时,客户端的操作可以进行,如果选择 “拒绝”,即满足配置的以下条件时,客户端的操作将被拒绝。 |
| 操作 | 授权策略针对不同的请求,包括连接(Connect),发送消息(Publish)和 订阅消息(Subscribe),支持多选。 |
| Topic | 支持使用通配符和策略变量,详见 表达式说明。 |
| 用户名 | 选填,填写单个用户名或单条资源表达式,支持使用通配符和策略变量,详见 表达式说明,为空表示支持所有用户名。 |
| 客户端 ID | 选填,填写单条资源表达式,支持使用通配符和策略变量,详见 表达式说明,为空或者 * 表示支持所有客户端。 |
| IP 地址 | 选填,仅支持填写单个 IP(如 192.168.0.1)或 CIDR 格式(如 192.168.1.0/24)。注意:客户端 IP 地址具有动态变化的特点,如果配置基于 IP 地址的 ACL 策略,可能存在授权失效或越权访问的安全风险。请根据业务场景谨慎设置。 |
| QoS | 选择授权策略支持的 QoS 等级。 |
| 消息类型 | 选择授权策略支持的消息类型:保留消息和普通消息,全部勾选表示支持所有消息。 |
5. 单击创建策略,在弹窗中二次确定后完成创建,返回授权策略列表页。
6. 在策略列表页,可以手动调整策略鉴权顺序,服务端会按照当前的策略顺序进行鉴权,如果策略配置冲突,以排序更靠前的策略为准(即序号越小优先级越高)。
十六、复制策略
当有大量相似的策略任务需要创建时,你可以单击已创建好的策略操作栏的复制策略,仅需对差异点进行针对性调整,即可完成策略创建,有效提升相似策略的配置效率。
十八、允许所有客户端操作
{ "effect": "allow", "actions": [ "connect", "pub", "sub" ], "topics": [ "*" ], "condition": { "ip": "0.0.0.0/0", "clientId": "", "username": "", "qos": [ 0, 1, 2 ], "retain": [ "true", "false" ] }}
十九、拒绝所有客户端操作
{ "effect": "deny", "actions": [ "connect", "pub", "sub" ], "topics": [ "*" ], "condition": { "ip": "0.0.0.0/0", "clientId": "", "username": "", "qos": [ 0, 1, 2 ], "retain": [ "true", "false" ] }}
20、允许所有客户端发布消息到一个 Topic
{ "effect": "allow", "actions": [ "connect", "pub" ], "topics": [ "topicA/test" ], "condition": { "ip": "0.0.0.0/0", "clientId": "", "username": "", "qos": [ 0, 1, 2 ], "retain": [ "true", "false" ] }}
21、允许所有客户端发布消息到多个 Topic
{ "effect": "allow", "actions": [ "connect", "pub" ], "topics": [ "home/sensor", "device/1" ], "condition": { "ip": "0.0.0.0/0", "clientId": "", "username": "", "qos": [ 0, 1, 2 ], "retain": [ "true", "false" ] }}
22、允许客户端发送到任意子 Topic
{ "effect": "allow", "actions": [ "connect", "pub" ], "topics": [ "home/#", "device/+" ], "condition": { "ip": "0.0.0.0/0", "clientId": "", "username": "", "qos": [ 0, 1, 2 ], "retain": [ "true", "false" ] }}
23、允许客户端发送到指定前缀、后缀 Topic
{ "effect": "allow", "actions": [ "connect", "pub" ], "topics": [ "prefix*", "*suffix" ], "condition": { "ip": "0.0.0.0/0", "clientId": "", "username": "", "qos": [ 0, 1, 2 ], "retain": [ "true", "false" ] }}
24、允许 client-Id 包含 username 的 client 连接
{ "effect": "allow", "actions": [ "connect" ], "topics": [ "*" ], "condition": { "ip": "0.0.0.0/0", "clientId": "*${Username}*", "username": "", "qos": [ 0, 1, 2 ], "retain": [ "true", "false" ] }}
25、拒绝 username 中包含 root 的客户端连接
{ "effect": "deny", "actions": [ "connect" ], "topics": [ "*" ], "condition": { "ip": "0.0.0.0/0", "clientId": "*", "username": "*root*", "qos": [ 0, 1, 2 ], "retain": [ "true", "false" ] }}
26、仅允许客户端 IP 在指定网段订阅消息
{ "effect": "allow", "actions": [ "connect", "sub" ], "topics": [ "*" ], "condition": { "ip": "192.168.0.0/16", "clientId": "*", "username": "*", "qos": [ 0, 1, 2 ], "retain": [ "true", "false" ] }}
27、客户端 ClientId 与 BYOC 证书 CommonName 匹配的客户端允许发送和订阅特定消息
{ "effect": "allow", "actions": [ "connect", "pub", "sub" ], "topics": [ "home/${Username}/+", "sensor/${ClientId}/#" ], "condition": { "ip": "192.168.0.0/16", "clientId": "*${Certificate.Subject.CommonName}*", "username": "*", "qos": [ 0, 1, 2 ], "retain": [ "true", "false" ] }}
28、允许从 ClientId 中提取子字符串以识别匹配请求订阅的 topic
{ "effect":"allow", "actions":["sub"], "topics":["/device/${clientId.substring(4)}/+"], "condition": { "ip": "0.0.0.0/0", "clientId": "", "username": "", "qos": [ 0, 1, 2 ], "retain": [ "true", "false" ] }}
29、允许设备仅发布消息到以证书 CommonName 中提取的设备编号命名的 Topic
注意:示例说明:
注意:假设证书的 Common Name 为
注意:“7F2A9C31-55B8-4E90-AB12-3C9D4E5F6A7B.CFG-01.ZN-East-02.SN20260101AB88XQ.CN.devices.adc.cloud",
注意:预期提取结果为"SN20260101AB88XQ",即设备编号位于按 “.” 分段后的倒数第 5 段。此处的设备编号提取支持以下两种写法,函数说明见上表:
{ "effect": "allow", "actions": [ "connect", "pub" ], "topics": [ "device/${Certificate.Subject.CommonName.nthToken('.', -5)}/status" ], "condition": { "ip": "0.0.0.0/0", "clientId": "", "username": "", "qos": [ 0, 1, 2 ], "retain": [ "true", "false" ] }}