重要
本页包含使用 Kubernetes 部署清单(目前为预览版)管理 Azure IoT 操作组件的说明。 此功能存在若干限制,不应该用于生产工作负载。
有关 beta 版本、预览版或尚未正式发布的版本的 Azure 功能所适用的法律条款,请参阅 Microsoft Azure 预览版的补充使用条款。
授权策略确定客户端可以在代理上执行的操作,例如连接、发布或订阅主题。 将 MQTT 代理配置为将一个或多个授权策略与 BrokerAuthorization 资源配合使用。 每个 BrokerAuthorization 资源都包含一个规则列表,用于指定授权策略的主体和资源。
将 BrokerAuthorization 链接到 BrokerListener
若要将 BrokerListener 资源链接到 BrokerAuthorization 资源,请在 BrokerListener 资源的 authorizationRef
设置中指定 ports
字段。 与 BrokerAuthentication 类似,BrokerAuthorization 资源可以链接到多个 BrokerListener 端口。 授权策略适用于所有链接的侦听器端口。 与 BrokerAuthentication 相比,存在一个关键差异:
重要
若要将 BrokerAuthorization 配置应用于侦听器端口,还必须将至少一个 BrokerAuthentication 资源链接到该侦听器端口。
若要了解 BrokerListener 的详细信息,请参阅 BrokerListener 资源。
授权规则
若要配置授权策略,首先需要在 Kubernetes 群集中创建 BrokerAuthorization 资源。 以下部分提供了有关如何为使用用户名、属性、X.509 证书和 Kubernetes 服务帐户令牌 (SAT) 的客户端配置授权的示例。 有关可用设置的列表,请参阅代理身份验证 API 参考。
以下示例演示如何使用用户名和属性创建 BrokerAuthorization 资源。
在 Azure 门户中,转到 IoT 操作实例。
在“组件”下,选择“MQTT 代理”。
选择授权选项卡。
选择现有身份验证策略,或通过选择“创建授权策略”来创建新的身份验证策略。
使用 az iot ops broker authz apply 命令创建或更改授权策略。
az iot ops broker authz apply --resource-group <ResourceGroupName> --instance <AioInstanceName> --broker <BrokerName> --name <AuthenticationResourceName> --config-file <ConfigFilePathAndName>
在此示例中,假定一个配置文件 my-authz-policy.json
,其中包含存储在用户主目录中的以下内容:
{
"authorizationPolicies": {
"cache": "Enabled",
"rules": [
{
"brokerResources": [
{
"clientIds": [],
"method": "Connect",
"topics": []
},
{
"clientIds": [],
"method": "Publish",
"topics": [
"odd-numbered-orders"
]
},
{
"clientIds": [],
"method": "Subscribe",
"topics": [
"orders"
]
}
],
"principals": {
"attributes": [
{
"group": "authz-sat"
}
],
"clientIds": [],
"usernames": []
}
}
]
}
}
用于创建新的授权策略 my-authz-policy
的示例命令为:
az iot ops broker authn apply --resource-group myResourceGroupName --instance myAioInstanceName --broker default --name my-authz-policy --config-file ~/my-authz-policy.json
若要编辑授权策略,请创建包含以下内容的 .bicep
文件。 根据需要更新设置,并将占位符值(如 <AIO_INSTANCE_NAME>
)替换为你自己的值。
param aioInstanceName string = '<AIO_INSTANCE_NAME>'
param customLocationName string = '<CUSTOM_LOCATION_NAME>'
param policyName string = '<POLICY_NAME>'
resource aioInstance 'Microsoft.IoTOperations/instances@2024-11-01' existing = {
name: aioInstanceName
}
resource customLocation 'Microsoft.ExtendedLocation/customLocations@2021-08-31-preview' existing = {
name: customLocationName
}
resource defaultBroker 'Microsoft.IoTOperations/instances/brokers@2024-11-01' existing = {
parent: aioInstance
name: 'default'
}
resource brokerAuthorization 'Microsoft.IoTOperations/instances/brokers/authorizations@2024-11-01' = {
parent: defaultBroker
name: policyName
extendedLocation: {
name: customLocation.id
type: 'CustomLocation'
}
properties: {
authorizationPolicies: {
cache: 'Enabled'
rules: [
{
principals: {
clientIds: [
'temperature-sensor'
'humidity-sensor'
]
attributes: [
{
city: 'seattle'
organization: 'contoso'
}
]
}
brokerResources: [
{
method: 'Connect'
}
{
method: 'Publish'
topics: [
'/telemetry/{principal.clientId}'
'/telemetry/{principal.attributes.organization}'
]
}
{
method: 'Subscribe'
topics: [
'/commands/{principal.attributes.organization}'
]
}
]
}
]
}
}
}
使用 Azure CLI 部署 Bicep 文件:
az deployment group create --resource-group <RESOURCE_GROUP> --template-file <FILE>.bicep
apiVersion: mqttbroker.iotoperations.azure.com/v1
kind: BrokerAuthorization
metadata:
name: "my-authz-policies"
namespace: azure-iot-operations
spec:
authorizationPolicies:
cache: Enabled
rules:
- principals:
clientIds:
- "temperature-sensor"
- "humidity-sensor"
attributes:
- city: "seattle"
organization: "contoso"
brokerResources:
- method: Connect
- method: Publish
topics:
- "/telemetry/{principal.clientId}"
- "/telemetry/{principal.attributes.organization}"
- method: Subscribe
topics:
- "/commands/{principal.attributes.organization}"
若要创建此 BrokerAuthorization 资源,请将 YAML 清单应用到 Kubernetes 群集。
此代理授权允许具有客户端 ID temperature-sensor
或 humidity-sensor
的客户端,或者具有属性 organization
(值为 contoso
)的客户端和具有属性 city
(值为 seattle
)的客户端执行以下操作:
- 连接到中转站。
- 将消息发布到其客户端 ID 和组织所在范围的遥测主题。 例如:
temperature-sensor
可以发布到 /telemetry/temperature-sensor
和 /telemetry/contoso
。
humidity-sensor
可以发布到 /telemetry/humidity-sensor
和 /telemetry/contoso
。
some-other-username
可以发布到 /telemetry/contoso
。
- 订阅其组织所在范围的
/commands/
主题。 例如:
temperature-sensor
可以订阅 /commands/contoso
。
some-other-username
可以订阅 /commands/contoso
。
使用用户名进行授权
若要使用 MQTT 用户名进行授权,请将其以数组的形式指定在 principals.usernames
下。 根据身份验证方法的不同,用户名可能无法验证:
- Kubernetes SAT - 用户名不应用于授权,因为对于采用增强身份验证的 MQTTv5,用户名无法完成验证。
- X.509 - 用户名与证书中的公用名 (CN) 相匹配,可用于授权规则。
- 自定义 - 只有在自定义身份验证将验证用户名的情况下,用户名才可以用于授权规则。
为了防止出现安全问题,只有当可以验证 MQTT 用户名时,才能将其用于代理授权。
根据客户端 ID 进一步限制访问
由于 principals
字段是逻辑 OR
,因此可以通过将 clientIds
字段添加到 brokerResources
字段来进一步限制基于客户端 ID 的访问。 例如,若要允许客户端 ID 以生成编号开头的客户端连接遥测数据并将其发布到其生成范围的主题,请使用以下配置:
在授权策略的代理授权规则中,使用以下配置:
[
{
"brokerResources": [
{
"clientIds": [
"{principal.attributes.building}*"
],
"method": "Connect",
"topics": []
},
{
"clientIds": [],
"method": "Publish",
"topics": [
"sensors/{principal.attributes.building}/{principal.clientId}/telemetry"
]
}
],
"principals": {
"attributes": [
{
"building": "building22"
},
{
"building": "building23"
}
]
}
}
]
使用 az iot ops broker authz apply 命令创建或更改授权策略。
az iot ops broker authz apply --resource-group <ResourceGroupName> --instance <AioInstanceName> --broker <BrokerName> --name <AuthenticationResourceName> --config-file <ConfigFilePathAndName>
在授权策略的中转站授权规则中,创建一个名为以下配置的配置文件 client-id-policy.json
,该文件存储在用户的主目录中:
{
"authorizationPolicies": {
"cache": "Enabled",
"rules": [
{
"brokerResources": [
{
"clientIds": [
"{principal.attributes.building}*"
],
"method": "Connect",
"topics": []
},
{
"clientIds": [],
"method": "Publish",
"topics": [
"sensors/{principal.attributes.building}/{principal.clientId}/telemetry"
]
}
],
"principals": {
"attributes": [
{
"building": "building22"
},
{
"building": "building23"
}
]
}
}
]
}
}
用于创建新的授权策略 client-id-authz-policy
的示例命令为:
az iot ops broker authn apply --resource-group myResourceGroupName --instance myAioInstanceName --broker default --name my-authz-policy --config-file ~/client-id-authz-policy.json
若要编辑授权策略,请创建包含以下内容的 .bicep
文件。 根据需要更新设置,并将占位符值(如 <AIO_INSTANCE_NAME>
)替换为你自己的值。
param aioInstanceName string = '<AIO_INSTANCE_NAME>'
param customLocationName string = '<CUSTOM_LOCATION_NAME>'
param policyName string = '<POLICY_NAME>'
resource aioInstance 'Microsoft.IoTOperations/instances@2024-11-01' existing = {
name: aioInstanceName
}
resource customLocation 'Microsoft.ExtendedLocation/customLocations@2021-08-31-preview' existing = {
name: customLocationName
}
resource defaultBroker 'Microsoft.IoTOperations/instances/brokers@2024-11-01' existing = {
parent: aioInstance
name: 'default'
}
resource brokerAuthorization 'Microsoft.IoTOperations/instances/brokers/authorizations@2024-11-01' = {
parent: defaultBroker
name: policyName
extendedLocation: {
name: customLocation.id
type: 'CustomLocation'
}
properties: {
authorizationPolicies: {
cache: 'Enabled'
rules: [
{
principals: {
attributes: [
{
building: 'building22'
}
{
building: 'building23'
}
]
}
brokerResources: [
{
method: 'Connect'
clientIds: [
'{principal.attributes.building}*' // client IDs must start with building22
]
}
{
method: 'Publish'
topics: [
'sensors/{principal.attributes.building}/{principal.clientId}/telemetry'
]
}
]
}
]
}
}
}
使用 Azure CLI 部署 Bicep 文件:
az deployment group create --resource-group <RESOURCE_GROUP> --template-file <FILE>.bicep
apiVersion: mqttbroker.iotoperations.azure.com/v1
kind: BrokerAuthorization
metadata:
name: "my-authz-policies"
namespace: azure-iot-operations
spec:
authorizationPolicies:
cache: Enabled
rules:
- principals:
attributes:
- building: "building22"
- building: "building23"
brokerResources:
- method: Connect
clientIds:
- "{principal.attributes.building}*" # client IDs must start with building22
- method: Publish
topics:
- "sensors/{principal.attributes.building}/{principal.clientId}/telemetry"
此处,如果未在 clientIds
方法下设置 Connect
,则只要客户端的 building
属性设置为 building22
或 building23
,则具有任何客户端 ID 的客户端就可以进行连接。 当添加 clientIds
字段时,只有客户端 ID 以 building22
或 building23
开头的客户端才能连接。 此指定可以确保客户端具有正确的属性,并且客户端 ID 与预期模式匹配。
授权使用 X.509 身份验证的客户端
你可以为使用 X.509 证书进行身份验证的客户端提供授权,允许其根据其证书上(或其在证书链中的上级颁发证书上)存在的 X.509 属性访问资源。
使用属性
若要基于客户端证书的属性、其根 CA 或中间 CA 创建规则,请在 BrokerAuthorization 资源中定义 X.509 属性。 有关详细信息,请参阅证书属性。
使用客户端证书主体公用名作为用户名
若要仅基于客户端证书主体 CN 创建授权策略,请基于 CN 创建规则。
例如,如果客户端具有主体为 CN = smart-lock
的证书,则其用户名为 smart-lock
。 然后,像平时一样创建授权策略。
授权使用 Kubernetes 服务帐户令牌的客户端
在服务帐户注释中设置 SAT 的授权属性。 例如,若要添加具有值 group
且名为 authz-sat
的授权属性,请运行以下命令:
kubectl annotate serviceaccount mqtt-client aio-broker-auth/group=authz-sat
属性注释必须以 aio-broker-auth/
开头,以便将其与其他注释区分开来。
由于应用程序具有名为 authz-sat
的授权属性,因此无需提供 clientId
或 username
值。 相应的 BrokerAuthorization 资源使用此属性作为主体,例如:
在授权策略的代理授权规则中,使用以下配置:
[
{
"brokerResources": [
{
"clientIds": [],
"method": "Connect",
"topics": []
},
{
"clientIds": [],
"method": "Publish",
"topics": [
"odd-numbered-orders"
]
},
{
"clientIds": [],
"method": "Subscribe",
"topics": [
"orders"
]
}
],
"principals": {
"attributes": [
{
"group": "authz-sat"
}
]
}
}
]
使用 az iot ops broker authz apply 命令创建或更改授权策略。
az iot ops broker authz apply --resource-group <ResourceGroupName> --instance <AioInstanceName> --broker <BrokerName> --name <AuthenticationResourceName> --config-file <ConfigFilePathAndName>
在此示例中,假定一个配置文件 my-authz-policy.json
,其中包含存储在用户主目录中的以下内容:
{
"authorizationPolicies": {
"cache": "Enabled",
"rules": [
{
"brokerResources": [
{
"clientIds": [],
"method": "Connect",
"topics": []
},
{
"clientIds": [],
"method": "Publish",
"topics": [
"odd-numbered-orders"
]
},
{
"clientIds": [],
"method": "Subscribe",
"topics": [
"orders"
]
}
],
"principals": {
"attributes": [
{
"group": "authz-sat"
}
],
"clientIds": [],
"usernames": []
}
}
]
}
}
用于创建新的授权策略 my-authz-policy
的示例命令为:
az iot ops broker authn apply --resource-group myResourceGroupName --instance myAioInstanceName --broker default --name my-authz-policy --config-file ~/my-authz-policy.json
若要编辑授权策略,请创建包含以下内容的 .bicep
文件。 根据需要更新设置,并将占位符值(如 <AIO_INSTANCE_NAME>
)替换为你自己的值。
param aioInstanceName string = '<AIO_INSTANCE_NAME>'
param customLocationName string = '<CUSTOM_LOCATION_NAME>'
param policyName string = '<POLICY_NAME>'
resource aioInstance 'Microsoft.IoTOperations/instances@2024-11-01' existing = {
name: aioInstanceName
}
resource customLocation 'Microsoft.ExtendedLocation/customLocations@2021-08-31-preview' existing = {
name: customLocationName
}
resource defaultBroker 'Microsoft.IoTOperations/instances/brokers@2024-11-01' existing = {
parent: aioInstance
name: 'default'
}
resource brokerAuthorization 'Microsoft.IoTOperations/instances/brokers/authorizations@2024-11-01' = {
parent: defaultBroker
name: policyName
extendedLocation: {
name: customLocation.id
type: 'CustomLocation'
}
properties: {
authorizationPolicies: {
rules: [
{
principals: {
attributes: [
{
group: 'authz-sat'
}
]
}
brokerResources: [
{
method: 'Connect'
}
{
method: 'Publish'
topics: [
'odd-numbered-orders'
]
}
{
method: 'Subscribe'
topics: [
'orders'
]
}
]
}
]
}
}
}
使用 Azure CLI 部署 Bicep 文件:
az deployment group create --resource-group <RESOURCE_GROUP> --template-file <FILE>.bicep
apiVersion: mqttbroker.iotoperations.azure.com/v1
kind: BrokerAuthorization
metadata:
name: "my-authz-policies"
namespace: azure-iot-operations
spec:
authorizationPolicies:
cache: Enabled
rules:
- principals:
attributes:
- group: "authz-sat"
brokerResources:
- method: Connect
- method: Publish
topics:
- "odd-numbered-orders"
- method: Subscribe
topics:
- "orders"
若要详细了解示例,请参阅使用 Dapr 客户端设置授权策略。
状态存储
MQTT 代理会提供一个可供客户端用于存储状态的状态存储。 你还可以将状态存储配置为高度可用。
若要为使用状态存储的客户端设置授权,请提供以下权限:
- 要发布到系统密钥值存储
$services/statestore/_any_/command/invoke/request
主题的权限
- 用于订阅响应主题(是在初始发布期间作为参数来设置的)
<response_topic>/#
的权限
状态存储键
状态存储将通过 MQTT 代理在主题 statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/command/invoke
上进行访问。
由于客户端有权访问该主题,因此你可以在 MQTT 代理 stateStoreResources
配置的 brokerResources
部分下指定键和访问级别。
stateStoreResources
部分格式包括访问级别、模式指示器和模式。
将 stateStoreResources
部分包含在授权策略的规则中。
"stateStoreResources": [
{
"method": "", // Values: read, write, readwrite
"keyType": "", //Values: string, pattern, binary. Default is pattern
"keys": [
// List of patterns to match
]
},
]
将 stateStoreResources
部分包含在授权策略的规则中。
"stateStoreResources": [
{
"method": "", // Values: read, write, readwrite
"keyType": "", //Values: string, pattern, binary. Default is pattern
"keys": [
// List of patterns to match
]
},
]
在 Bicep 中,将 stateStoreResources
部分包含在授权策略中。
stateStoreResources: [
{
method: '' // Values: read, write, readwrite
keyType: '' //Values: string, pattern, binary. Default is pattern
keys: [
// List of patterns to match
]
}
{
method: 'ReadWrite'
keyType: 'Binary'
keys: [
'xxxxxxxxxxxxxxxxxxxx'
]
}
]
在自定义资源定义中,将 stateStoreResources
部分包含在授权策略中。
stateStoreResources:
- method: # Values: read, write, readwrite
keyType: # Values: string, pattern, binary. Default is pattern
keys:
- # List of patterns to match
method
字段指定访问级别:
- 使用
read
指定读取访问。 使用 write
指定写入访问。 使用 readwrite
指定读取和写入访问。
- 访问级别是必需的。
- 读取访问级别意味着可以执行
get
和 keynotify
操作。
- 写入访问级别意味着可以执行
set
、del
和 vdel
操作。
keyType
字段指定键匹配的类型:
pattern
:用于指定 glob 样式模式匹配。
string
:用于进行精确匹配,例如,当键包含可能作为模式匹配的字符时(*
、?
、[0-9]
)
binary
:用于匹配二进制键。
keys
字段指定要匹配的键。 你可以将这些键指定为 Glob 样式模式、令牌替代或确切字符串。
下面是一个展示如何创作状态存储资源的示例。
在授权策略的代理授权规则中,添加类似的配置:
[
{
"brokerResources": [
{
"clientIds": [
"{principal.attributes.building}*"
],
"method": "Connect"
},
{
"method": "Publish",
"topics": [
"sensors/{principal.attributes.building}/{principal.clientId}/telemetry/*"
]
},
{
"method": "Subscribe",
"topics": [
"commands/{principal.attributes.organization}"
]
}
],
"principals": {
"attributes": [
{
"building": "17",
"organization": "contoso"
}
],
"usernames": [
"temperature-sensor",
"humidity-sensor"
]
},
"stateStoreResources": [
{
"method": "Read",
"keyType": "Pattern",
"keys": [
"myreadkey",
"myotherkey?",
"mynumerickeysuffix[0-9]",
"clients/{principal.clientId}/*"
]
},
{
"method": "ReadWrite",
"keyType": "Binary",
"keys": [
"xxxxxxxxxxxxxxxxxxxx"
]
}
]
}
]
在此示例中,假定在用户的主目录中命名 state-store-authz-policy.json
的配置文件。 在授权策略的代理授权规则中,添加类似的配置:
{
"authorizationPolicies": {
"cache": "Enabled",
"rules": [
{
"brokerResources": [
{
"clientIds": [
"{principal.attributes.building}*"
],
"method": "Connect"
},
{
"method": "Publish",
"topics": [
"sensors/{principal.attributes.building}/{principal.clientId}/telemetry/*"
]
},
{
"method": "Subscribe",
"topics": [
"commands/{principal.attributes.organization}"
]
}
],
"principals": {
"attributes": [
{
"building": "17",
"organization": "contoso"
}
],
"usernames": [
"temperature-sensor",
"humidity-sensor"
]
},
"stateStoreResources": [
{
"method": "Read",
"keyType": "Pattern",
"keys": [
"myreadkey",
"myotherkey?",
"mynumerickeysuffix[0-9]",
"clients/{principal.clientId}/*"
]
},
{
"method": "ReadWrite",
"keyType": "Binary",
"keys": [
"xxxxxxxxxxxxxxxxxxxx"
]
}
]
}
]
}
}
用于创建新的授权策略 state-store-authz-policy
的示例命令为:
az iot ops broker authn apply --resource-group myResourceGroupName --instance myAioInstanceName --broker default --name my-authz-policy --config-file ~/state-store-authz-policy.json
若要编辑授权策略,请创建包含以下内容的 .bicep
文件。 根据需要更新设置,并将占位符值(如 <AIO_INSTANCE_NAME>
)替换为你自己的值。
param aioInstanceName string = '<AIO_INSTANCE_NAME>'
param customLocationName string = '<CUSTOM_LOCATION_NAME>'
param policyName string = '<POLICY_NAME>'
resource aioInstance 'Microsoft.IoTOperations/instances@2024-11-01' existing = {
name: aioInstanceName
}
resource customLocation 'Microsoft.ExtendedLocation/customLocations@2021-08-31-preview' existing = {
name: customLocationName
}
resource defaultBroker 'Microsoft.IoTOperations/instances/brokers@2024-11-01' existing = {
parent: aioInstance
name: 'default'
}
resource brokerAuthorization 'Microsoft.IoTOperations/instances/brokers/authorizations@2024-11-01' = {
parent: defaultBroker
name: policyName
extendedLocation: {
name: customLocation.id
type: 'CustomLocation'
}
properties: {
authorizationPolicies: {
cache: 'Enabled'
rules: [
{
principals: {
usernames: [
'temperature-sensor'
'humidity-sensor'
]
attributes: [
{
city: 'seattle'
organization: 'contoso'
}
]
}
brokerResources: [
{
method: 'Connect'
}
{
method: 'Publish'
topics: [
'/telemetry/{principal.username}'
'/telemetry/{principal.attributes.organization}'
]
}
{
method: 'Subscribe'
topics: [
'/commands/{principal.attributes.organization}'
]
}
]
stateStoreResources: [
{
method: 'Read'
keyType: 'Pattern'
keys: [
'myreadkey'
'myotherkey?'
'mynumerickeysuffix[0-9]'
'clients/{principal.clientId}/*'
]
}
{
method: 'ReadWrite'
keyType: 'Binary'
keys: [
'xxxxxxxxxxxxxxxxxxxx'
]
}
]
}
]
}
}
}
使用 Azure CLI 部署 Bicep 文件:
az deployment group create --resource-group <RESOURCE_GROUP> --template-file <FILE>.bicep
stateStoreResources:
- method: Read # Read includes Get, Notify
keyType: "pattern" # string, pattern, binary
keys:
- "myreadkey" # explicit read access on key: myreadkey
- "myotherkey?" # single digit wildcard
- "mynumerickeysuffix[0-9]" # single digit number range
- "clients/{principal.clientId}/*" # use token substitution and a wildcard for per-client sandboxing
- method: ReadWrite # ReadWrite access includes Get, Notify, Set, Del
keyType: "binary" # binary keys have exact match, no patterns
keys:
- "xxxxxxxxxxxxxxxxxxxx" # base-64 encoded binary key.
更新授权
你可以在运行时更新代理授权资源,而无需重启。 策略更新时连接的所有客户端都会断开连接。 还支持更改策略类型。
kubectl edit brokerauthorization my-authz-policies
禁用授权
- 在 Azure 门户中,转到 IoT 操作实例。
- 在“组件”下,选择“MQTT 代理”。
- 从列表中选择要编辑的代理侦听器。
- 在要禁用授权的端口上,请在授权下拉列表中选择“无”。
使用 az iot ops broker listener port add 命令来禁用端口的授权功能。 若要禁用身份验证,请不要包含 --authz-ref
参数。
az iot ops broker listener port add --resource-group <ResourceGroupName> --instance <AioInstanceName> --broker default --listener <ListenerName> --port <ListenerServicePort>
以下示例禁用对名为 aio-broker-loadbalancer
侦听器的端口 8884 的授权:
az iot ops broker listener port add --resource-group myResourceGroupName --instance myAioInstanceName --broker default --listener aio-broker-loadbalancer --authn-ref default --port 8884
若要禁用授权,请在 BrokerListener 资源的 authorizationRef
设置中省略 ports
。
若要禁用授权,请在 BrokerListener 资源的 authorizationRef
设置中省略 ports
。
MQTT 3.1.1 中未经授权的发布
使用 MQTT 3.1.1 时,若发布被拒绝,客户端会收到 PUBACK,而不会收到错误消息,因为协议版本不支持返回错误代码。 MQTTv5 则会在发布被拒绝时返回 PUBACK 及原因代码 135(未授权)。
相关内容