账户登录 Cluster(AccountLogin)

Cluster ID: 0x050E  |  所在 Endpoint: 媒体端点(流媒体设备、智能电视上的内容应用)

AccountLogin 负责在智能电视或流媒体设备上完成内容提供商的账户认证。 当用户的手机 App 已登录某个视频服务(如 Netflix、YouTube), 想让电视上的对应内容应用也获得该账户的访问权限时,就需要通过这个 Cluster 完成认证。 它不负责播放控制(那是 MediaPlayback 的事), 而是解决「电视怎么知道你是谁」这个问题。

核心定位

如果把电视上的内容应用比作一个需要门禁卡的影院,AccountLogin 就是发临时门禁卡的柜台。 你的手机(Commissioner)拿着身份证(账户信息)去柜台领一张临时卡(Setup PIN), 再用这张卡刷卡进入(Login)。看完电影后,交还临时卡(Logout)。 整个过程的关键是:临时卡是一次性的,而且领卡和刷卡都必须在限定时间内完成(Timed Invoke)。

认证流程

AccountLogin 的认证是一个三步握手流程,由手机 App(Commissioner)主导:

  1. 请求 PIN:手机 App 向电视上的内容应用发送 GetSetupPIN, 携带一个临时账户标识(TempAccountIdentifier)。 这个标识由手机端的内容提供商 App 生成,通常是一个关联到用户账户的临时令牌
  2. 获取 PIN:电视端的内容应用验证临时标识后, 返回一个临时 Setup PIN(最长 8 个字符)。 这个 PIN 是一次性的,用于下一步的登录
  3. 执行登录:手机 App 将临时标识和 Setup PIN 一起发送 Login 命令, 电视端验证通过后,该节点获得内容访问权限
所有命令都要求 Timed Invoke

AccountLogin 的三个命令(GetSetupPIN、Login、Logout)全部要求使用 Timed Invoke。 这意味着每个命令在发送前必须先发起一个限时事务(Timed Request), 设备只在事务窗口内接受命令。这是防止中间人重放攻击的关键安全措施。

命令(Commands)

AccountLogin Cluster 共有 3 个命令和 1 个响应。 其中 GetSetupPIN 有专属的响应结构体 GetSetupPINResponse, Login 和 Logout 通过通用 Status 返回结果。 点击下方表格中的命令 ID 可跳转到对应的详细说明。

ID 名称 方向 说明
0x00 GetSetupPIN Client → Server 请求临时 Setup PIN
0x01 GetSetupPINResponse Server → Client 返回临时 Setup PIN
0x02 Login Client → Server 使用临时标识 + PIN 登录
0x03 Logout Client → Server 登出当前账户

GetSetupPIN —— 请求 Setup PIN(0x00)

由手机 App(Client)发送给电视端的内容应用(Server),请求一个临时的 Setup PIN。 内容应用收到后,会根据 TempAccountIdentifier 查询对应的用户账户信息, 如果确认有效,则生成并返回一个临时 PIN。

参数类型说明
TempAccountIdentifier string 手机端内容提供商 App 生成的临时账户标识。最大长度 100 字符。由内容提供商自行定义格式,通常是与用户账户关联的临时令牌
TempAccountIdentifier 是什么

这个字段不是用户的用户名或密码。 它是手机端 App 在用户已登录状态下生成的一个临时令牌(token), 用于让电视端的内容应用识别「这个请求来自哪个已认证用户」。 具体格式和生成方式由内容提供商(如 Netflix、Disney+)自行定义。

GetSetupPINResponse —— 返回 Setup PIN(0x01)

电视端内容应用对 GetSetupPIN 的响应。如果临时账户标识有效,返回一个可用于 Login 的临时 PIN。

字段类型说明
SetupPIN string 临时 Setup PIN,最大长度 8 字符。用于后续 Login 命令。PIN 是临时的,内容应用可以自行决定有效期
PIN 是临时的

SetupPIN 应当是一次性或短时有效的。内容应用不应该返回固定不变的 PIN, 否则存在被重放攻击利用的风险。建议在 Login 成功后立即失效该 PIN, 或者设置一个较短的过期时间(如 2 分钟)。

Login —— 登录(0x02)

使用前面获取的临时账户标识和 Setup PIN 完成登录。 登录成功后,发起请求的节点获得该内容应用的访问权限,可以浏览和播放用户订阅的内容。

参数类型说明
TempAccountIdentifier string 与 GetSetupPIN 相同的临时账户标识
SetupPIN string GetSetupPINResponse 返回的临时 PIN
Node node-id(可选) 指定要授权的节点 ID。如果省略,则授权发送此命令的节点。当手机代替另一台设备请求登录时使用
Login 失败的常见原因
  • PIN 已过期 —— 从 GetSetupPIN 到 Login 之间间隔太久,PIN 已失效
  • PIN 不匹配 —— TempAccountIdentifier 与 SetupPIN 不对应
  • 未使用 Timed Invoke —— 命令没有通过限时事务发送,设备直接拒绝
  • 账户标识无效 —— TempAccountIdentifier 在内容提供商侧已失效或不存在

Logout —— 登出(0x03)

撤销之前通过 Login 获得的访问权限。登出后,对应节点将无法再访问该内容应用的用户内容。

参数类型说明
Node node-id(可选) 指定要登出的节点 ID。如果省略,则登出发送此命令的节点
使用场景

用户在手机上退出内容提供商账户、切换账户、或手动管理设备访问权限时调用。 也可以由自动化规则触发 —— 例如当手机离开家庭网络时自动登出电视上的内容应用。

属性说明

AccountLogin Cluster 没有应用层面的自定义属性。 它只包含 Matter 规范要求的全局属性(Global Attributes),这些属性描述 Cluster 本身的元信息。

ID 名称 类型 说明
0xFFF8 GeneratedCommandList list<command-id> Server 能生成的响应命令列表。通常为 [0x01](GetSetupPINResponse)
0xFFF9 AcceptedCommandList list<command-id> Server 能接受的命令列表。通常为 [0x00, 0x02, 0x03](GetSetupPIN / Login / Logout)
0xFFFA EventList 新版已移除 list<event-id> 旧版本中列出本 Cluster 支持的事件 ID。新版 Matter 已从全局属性中移除 EventList,设备不再上报它
0xFFFB AttributeList list<attrib-id> 本 Cluster 包含的属性 ID 列表
0xFFFC FeatureMap map32 当前无可选特性,值为 0
0xFFFD ClusterRevision uint16 Cluster 规范版本
为什么没有应用属性

AccountLogin 是一个纯命令驱动的 Cluster。 它的核心功能(认证)是通过命令交互完成的,不需要持久存储状态到属性中。 登录状态由内容应用自身管理,而非通过 Cluster 属性暴露。 这与 AdministratorCommissioning 等「有状态」的 Cluster 形成对比。

安全机制

AccountLogin 涉及用户账户认证,安全要求高于普通控制类 Cluster。 Matter 规范对它施加了以下约束:

Timed Invoke(限时调用)

所有三个命令都必须使用 Timed Invoke 发送。 Timed Invoke 的工作方式:

  1. Client 先发一个 TimedRequest,声明后续命令的超时时间
  2. Server 回复确认并开始计时
  3. Client 在超时窗口内发送实际命令(如 Login)
  4. 超时窗口关闭后,Server 不再接受该命令

这种机制的核心目的是防止重放攻击:即使攻击者截获了 Login 命令的完整数据包, 也无法在超时窗口关闭后重新发送。

临时 PIN 机制

Setup PIN 是认证流程中的第二道防线:

  • PIN 由电视端内容应用动态生成,不是固定密码
  • PIN 绑定到特定的 TempAccountIdentifier,不能跨账户使用
  • PIN 应设置有效期(规范建议尽可能短),过期后即使知道 PIN 也无法登录
  • PIN 使用后应立即失效,防止被二次使用

访问权限要求

AccountLogin 的命令需要 Administer 级别的访问权限(Access Privilege)。 这意味着只有在设备 ACL 中拥有管理员权限的节点才能调用这些命令, 普通的 Operate 级别权限不够。

示例数据

Cluster 属性读取

读取 AccountLogin Cluster 的全部属性(仅全局属性):

{
  // --- 全局属性 ---
  "0xFFF8": [0, 1],            // GeneratedCommandList = [GetSetupPINResponse]
  "0xFFF9": [0, 2, 3],         // AcceptedCommandList = [GetSetupPIN, Login, Logout]
  "0xFFFB": [                   // AttributeList
    0xFFF8, 0xFFF9,
    0xFFFB, 0xFFFC, 0xFFFD
  ],
  "0xFFFC": 0,                  // FeatureMap = 0(无可选特性)
  "0xFFFD": 2                   // ClusterRevision = 2
}

GetSetupPIN 交互示例

手机 App 向电视内容应用请求 Setup PIN:

// 手机 App → 电视内容应用:请求 Setup PIN
{
  "invokeRequests": [{
    "commandPath": {
      "endpointId": 3,
      "clusterId": "0x050E",
      "commandId": "0x00"              // GetSetupPIN
    },
    "commandFields": {
      "TempAccountIdentifier": "user_abc_token_20260901"
                                       // 手机端生成的临时账户标识
    },
    "timedRequest": true,              // 必须使用 Timed Invoke
    "interactionTimeoutMs": 10000
  }]
}

// 电视内容应用 → 手机 App:返回 Setup PIN
{
  "invokeResponseMessage": [{
    "commandPath": {
      "endpointId": 3,
      "clusterId": "0x050E",
      "commandId": "0x01"              // GetSetupPINResponse
    },
    "commandFields": {
      "SetupPIN": "34567890"           // 临时 PIN,用于后续 Login
    }
  }]
}

Login 交互示例

使用获取到的 PIN 完成登录:

// 手机 App → 电视内容应用:使用 PIN 登录
{
  "invokeRequests": [{
    "commandPath": {
      "endpointId": 3,
      "clusterId": "0x050E",
      "commandId": "0x02"              // Login
    },
    "commandFields": {
      "TempAccountIdentifier": "user_abc_token_20260901",
      "SetupPIN": "34567890",          // GetSetupPINResponse 返回的 PIN
      "Node": "0x0000000012345678"     // 可选:指定授权的节点 ID
    },
    "timedRequest": true,
    "interactionTimeoutMs": 10000
  }]
}

// 电视内容应用 → 手机 App:Status = SUCCESS

Logout 交互示例

登出当前账户:

// 手机 App → 电视内容应用:登出
{
  "invokeRequests": [{
    "commandPath": {
      "endpointId": 3,
      "clusterId": "0x050E",
      "commandId": "0x03"              // Logout
    },
    "commandFields": {
      "Node": "0x0000000012345678"     // 可选:指定要登出的节点 ID
    },
    "timedRequest": true,
    "interactionTimeoutMs": 10000
  }]
}

// 电视内容应用 → 手机 App:Status = SUCCESS
开发提示

所有命令示例中的 timedRequest: true 和 interactionTimeoutMs 不是可选的。 如果 SDK 没有自动处理 Timed Invoke,需要手动构造限时事务。 大多数 Matter SDK(如 CHIP Tool、connectedhomeip)在调用标记为 Timed Invoke 的命令时会自动处理, 但自定义实现需要注意这一点。

常见场景

场景 1:手机投屏时自动登录电视内容应用

背景:用户在手机上打开 Netflix App 并已登录,现在想在电视上观看。电视上已安装 Netflix 内容应用。

  1. 用户在手机 Netflix App 中选择「投射到电视」
  2. 手机发现电视上的 Netflix 内容应用所在的 Endpoint(例如 Endpoint 3)
  3. 手机 Netflix App 生成一个临时账户标识(关联到用户的 Netflix 账户)
  4. 手机向电视 Endpoint 3 发送 GetSetupPIN (0x00), 携带临时账户标识
  5. 电视端 Netflix 应用验证标识,生成临时 PIN 并返回
  6. 手机自动使用标识和 PIN 发送 Login (0x02)
  7. 登录成功 —— 电视上的 Netflix 现在可以访问用户的观看历史、收藏列表和订阅内容
  8. 用户在电视上选择内容播放,通过 MediaPlayback 控制播放

整个过程对用户来说是无感的:点击「投射」后,电视自动切换到已登录状态。 PIN 交换发生在后台,用户不需要在电视上手动输入任何信息。

场景 2:多用户切换与登出管理

背景:家庭中多人共用一台电视,每个人有自己的内容订阅账户。

  1. 用户 A 的手机已通过 Login 让电视登录了 A 的账户
  2. 用户 B 想切换到自己的账户:
    • B 的手机先发送 Logout (0x03) 登出 A 的会话 (如果 B 的节点有权限),或者 A 自己从手机端发送 Logout
    • B 的手机再执行完整的 GetSetupPIN → Login 流程登录 B 的账户
  3. 登出时机建议:
    • 用户主动切换账户时
    • 手机 App 退出登录时,同步登出所有已授权的电视
    • 设备管理页面中提供「退出所有设备」的选项

注意 Node 参数:Login 和 Logout 的 Node 参数允许一个节点代替另一个节点操作。 例如,家庭管理员可以从自己的手机登出其他家庭成员在电视上的会话。