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 用户名密码认证为例,成功场景的典型时序如下:

  1. 客户端建立 TCP/TLS 连接后,发送 CONNECT 报文,其中 Username 为 device-001,Password 为对应凭据,Clean Start 为 1。
  2. 服务端解析 CONNECT,校验协议版本、Client ID 合法性、用户名密码是否正确。
  3. 校验通过后,服务端返回 CONNACK,Reason Code 为 0x00,Session Present 为 0(因为 Clean Start 为 1,不恢复旧会话)。
  4. 客户端收到 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含义常见原因
0x00Success认证通过
0x80Unspecified error服务端内部异常
0x84Unsupported Protocol Version客户端协议版本与服务端不匹配
0x85Client Identifier not validClient ID 为空或格式非法
0x86Bad User Name or Password凭据错误
0x87Not authorized未提供认证信息或 ACL 拒绝
0x8CBad authentication methodAUTH 方法不被支持
0x18Continue authentication需要继续 AUTH 交互

排查时建议按“协议版本 → Client ID → 凭据 → 认证方法 → ACL”的顺序逐层确认。尤其要注意:0x87 既可能表示未认证,也可能表示已认证但 ACL 不允许当前操作,需要结合服务端日志区分。

MQTT 5.0 认证交互时序与状态机 客户端 Client 服务端 Broker CONNECT (ClientID, Username, Password) CONNACK 0x00 Success 状态:已连接 状态:已认证 CONNECT (错误凭据) CONNACK 0x86 Bad User/Password 状态:认证失败 状态:断开连接 AUTH 报文:仅 MQTT 5.0 增强认证使用

五、实操观察点

在实际抓包或日志分析中,可以重点关注以下内容:

  • CONNECT 报文中是否携带 Username/Password,以及 Authentication Method 是否与服务端配置一致。
  • CONNACK 的 Reason Code 是否为 0x00,Session Present 是否符合预期。
  • 是否出现 AUTH 报文往返,以及 AUTH 的 Reason Code 是否为 0x18 或 0x19。
  • 服务端日志中是否记录“认证失败”“ACL 拒绝”等关键字,用于区分 0x86 与 0x87。
建议在测试环境分别构造“正确凭据”“错误密码”“空用户名”“不支持的认证方法”四种场景,观察 CONNACK 返回码和客户端状态机变化,形成自己的错误码对照表。
注意:MQTT 3.1.1 没有 AUTH 报文,若客户端使用 3.1.1 而服务端期望 5.0 增强认证,可能直接返回 0x84 或 0x8C,需要先统一协议版本再排查凭据问题。

掌握 CONNECT、CONNACK、AUTH 的交互时序与错误码含义后,后续配置用户名密码认证、TLS 证书认证或 ACL 规则时,就能快速定位问题发生在认证的哪一环,而不是盲目修改配置。