3. MQTT认证流程拆解
MQTT 的认证过程并不是一个独立阶段,而是嵌入在连接建立过程之中的。理解 CONNECT、CONNACK 与 AUTH 三类报文如何交互,是排查“连不上”“认证失败”“权限不足”等问题的前提。本节从报文结构、交互时序、状态机变化和错误码四个角度拆解认证流程。
一、三类报文在认证中的角色
MQTT 5.0 中与认证直接相关的报文有三类:
- CONNECT:客户端发起连接时发送,携带 Client ID、用户名、密码、Keep Alive、Clean Start 等字段。认证信息主要放在 Payload 的 Username 和 Password 字段中,也可以放在 Properties 的 Authentication Method 与 Authentication Data 中。
- CONNACK:服务端对 CONNECT 的响应,返回 Reason Code、Session Present 以及可选的认证相关属性。Reason Code 为 0x00 表示成功,其他值表示失败。
- AUTH:MQTT 5.0 新增报文,用于增强认证(Enhanced Authentication)。当服务端需要多轮挑战—应答时,通过 AUTH 报文继续交互,而不是直接返回 CONNACK。
需要特别说明:AUTH 报文只在 MQTT 5.0 中存在,MQTT 3.1.1 没有 AUTH 报文,认证只能通过 CONNECT 中的用户名密码一次性完成。因此,如果客户端使用 3.1.1 协议版本,服务端不会发送 AUTH,认证失败会直接体现在 CONNACK 的返回码中。
二、成功场景的交互时序
以 MQTT 5.0 用户名密码认证为例,成功场景的典型时序如下:
- 客户端建立 TCP/TLS 连接后,发送 CONNECT 报文,其中 Username 为
device-001,Password 为对应凭据,Clean Start 为 1。 - 服务端解析 CONNECT,校验协议版本、Client ID 合法性、用户名密码是否正确。
- 校验通过后,服务端返回 CONNACK,Reason Code 为
0x00,Session Present 为 0(因为 Clean Start 为 1,不恢复旧会话)。 - 客户端收到 CONNACK 后,连接状态进入“已连接”,可以开始发送 PUBLISH、SUBSCRIBE 等报文。
如果服务端启用了增强认证,时序会多出 AUTH 往返:客户端在 CONNECT 中携带 Authentication Method,服务端返回 0x18(Continue authentication)的 CONNACK 或 AUTH 报文,客户端再发送 AUTH 报文携带认证数据,直到服务端返回 0x00 的 CONNACK 完成认证。
三、失败场景与状态机变化
认证失败时,服务端不会进入“已连接”状态,而是直接返回带错误码的 CONNACK,并关闭网络连接。客户端状态机从“连接中”转为“断开”,需要根据错误码决定是否重试。
常见失败场景包括:
- 用户名或密码错误:CONNACK Reason Code 为
0x86(Bad User Name or Password)。 - 客户端未提供认证信息:
0x87(Not authorized)。 - 认证方法不被支持:
0x8C(Bad authentication method)。 - 协议版本不支持:
0x84(Unsupported Protocol Version)。 - Client ID 不合法:
0x85(Client Identifier not valid)。
状态机层面,客户端在发送 CONNECT 后进入“等待 CONNACK”状态。收到 0x00 则进入“已连接”;收到非零 Reason Code 则进入“认证失败”状态,通常应停止自动重连或进入退避重试,避免因凭据错误导致频繁重连被服务端限流。
四、错误码含义与排查方向
| Reason Code | 含义 | 常见原因 |
|---|---|---|
| 0x00 | Success | 认证通过 |
| 0x80 | Unspecified error | 服务端内部异常 |
| 0x84 | Unsupported Protocol Version | 客户端协议版本与服务端不匹配 |
| 0x85 | Client Identifier not valid | Client ID 为空或格式非法 |
| 0x86 | Bad User Name or Password | 凭据错误 |
| 0x87 | Not authorized | 未提供认证信息或 ACL 拒绝 |
| 0x8C | Bad authentication method | AUTH 方法不被支持 |
| 0x18 | Continue authentication | 需要继续 AUTH 交互 |
排查时建议按“协议版本 → Client ID → 凭据 → 认证方法 → ACL”的顺序逐层确认。尤其要注意:0x87 既可能表示未认证,也可能表示已认证但 ACL 不允许当前操作,需要结合服务端日志区分。
五、实操观察点
在实际抓包或日志分析中,可以重点关注以下内容:
- CONNECT 报文中是否携带 Username/Password,以及 Authentication Method 是否与服务端配置一致。
- CONNACK 的 Reason Code 是否为 0x00,Session Present 是否符合预期。
- 是否出现 AUTH 报文往返,以及 AUTH 的 Reason Code 是否为 0x18 或 0x19。
- 服务端日志中是否记录“认证失败”“ACL 拒绝”等关键字,用于区分 0x86 与 0x87。
掌握 CONNECT、CONNACK、AUTH 的交互时序与错误码含义后,后续配置用户名密码认证、TLS 证书认证或 ACL 规则时,就能快速定位问题发生在认证的哪一环,而不是盲目修改配置。