nimeet 文档中心
English

AccessToken2 语义与权限位

权限位、频道名/uid 绑定、exp 与 pexp 分离、通配 Token、续期宽限,以及我们与声网的差异。

版本 v1.1.0 · 更新于 2026-10-26 · 修订 1

这一页讲 Token 本身的语义:里面有什么、谁签名、什么时候失效、越权会怎样。签发/续期/校验的接口调用方式见 Token 鉴权;两者的关系是「语义 vs 用法」。

一句话模型

Token = 项目 App ID + 频道名 + uid + 角色权限集 + 过期时间 的签名快照,用项目的 App Certificate 做 HMAC-SHA256。 服务端与 SDK 都把它当不透明字符串:不解密、不拼接、不缓存解析结果做鉴权判断。

线格式

text
nrt1.<base64url(payload JSON)>.<base64url(HMAC-SHA256(appCertificate, "nrt1.<base64url(payload)>"))>
段内容说明
前缀nrt1格式版本;将来若改结构会升到 nrt2,SDK 与网关同时兼容一段时间
payloadbase64url(JSON)字段见下表;不是加密,任何人都能解出来,所以不要往里塞敏感信息
签名base64url(HMAC-SHA256)用 appCertificate 签名;校验用常量时间比较,防时序侧信道

payload 字段

以下字段由 控制面组件 定义,并镜像到 接口定义:

字段类型含义
vnumber版本,当前 1
appstring项目 App ID(32 位十六进制)
chstring频道名;* 表示通配(任意频道)
uidnumber数字 uid,1..2147483647
rolehost \audience决定默认权限集
privstring[]实际权限位(见下表),是授权判断的唯一依据
iatnumber签发时间(epoch 秒)
expnumberToken 生命周期到期(epoch 秒)
pexpnumber权限到期(epoch 秒),恒 ≤ exp
saltnumber随机数,保证相同输入产生不同 Token(防指纹/重放聚类)
usrstring?身份提示,仅用于审计与日志关联,不参与授权

权限位

权限位含义hostaudience
join_channel允许进入频道✅✅
publish_audio允许发布音频✅—
publish_video允许发布视频✅—
publish_data允许发送数据通道消息✅—
subscribe允许订阅远端音视频✅✅

GET /v1/meta/privileges 返回这张表(按角色),客户端 SDK 与文档读的是同一份数据,避免「文档说 host 能发、实际被拒」。

exp 与 pexp 为什么要分开

声网 AccessToken2 把「Token 有效期」和「权限有效期」拆开,我们保持一致:

  • exp:Token 字符串本身还能不能被接受(续期窗口由它决定);
  • pexp:里面的权限还能不能用(通常更短,用于「先续期、后收紧权限」)。

三个典型的过期状态因此互不相同:

状态判定SDK 事件客户端应该做什么
权限即将过期now > pexp - 30stoken-privilege-will-expire调服务端续期,然后 renewToken(newToken)
权限已过期但 Token 未过期now > pexp 且 now ≤ exptoken-privilege-did-expire立刻续期;期间发布会被拒
Token 已过期now > exp连接被断开(错误号 -109)重新入会

服务端也会在权限过期前产生事件码 203(token_expiring)的回调,用于在服务端触发续期逻辑,见 回调事件参考。

通配 Token

ch = "*" 的 Token 可进任意频道,用于本地联调与「一个客户端试多个房间」。生产环境不建议:

  • 它把授权范围从「一个频道」放大到「整个项目」;
  • 一旦泄露,影响面是全部频道,而不是单个频道;
  • 审计时无法从 Token 反推用户本该在哪个频道。

通配 Token 只能通过显式请求 wildcard: true 签发,且 GET /v1/tokens/verify 会在响应里明确标出 wildcard: true。

校验顺序与拒绝原因

verifyToken 的判定顺序是固定的,排障时按顺序排除:

顺序拒绝原因(TokenRejection)对应 REST 错误码
1malformed / bad_prefixinvalid_token
2bad_versioninvalid_token
3invalid_signatureinvalid_token
4expiredtoken_expired
5not_yet_valid(iat 超前,默认容忍 5 秒时钟偏移)token_not_yet_valid
6channel_mismatchtoken_channel_mismatch
7uid_mismatchtoken_uid_mismatch
8privilege_expired / missing_privilegetoken_privilege_expired

签名校验先于任何业务校验:签名不对时不会告诉你频道名对不对,避免被当作探测接口。

uid 与 userId 的映射

Token 里只有数字 uid。IM 用户 id(字符串)通过 POST /v1/uids:resolve 映射,映射关系在签发 Token 时传入 userId 建立。两部分是独立链路:Token 合法但映射缺失时,/v1/uids:resolve 会返回部分结果(resolved / unresolved),不会让你整批失败。

安全实践(Token 相关部分)

  1. appCertificate 只放服务端,进密钥管理,不进镜像、不进前端 bundle、不进日志。
  2. Token TTL 默认按项目 tokenTtlSeconds,业务侧建议 1 小时内;长会话用续期而不是长 TTL。
  3. 不要把 salt 或 payload 当业务状态存储——它们会随每次签发变化。
  4. 轮换 appCertificate 会让所有已签发 Token 立即失效,必须在客户端有续期路径的时段内做。
  5. 权限最小化:观众端只签 audience,不要把 host 权限发给前端然后「靠 UI 限制」。

与其他页面的关系

本页由文档构建流水线生成 · 2026-10-31 01:24:02 UTC · 文档中心 v1.1.0.

内容依据公开 API 定义.

ni-meet 是自建 RTC PaaS,媒体面基于 LiveKit(Apache-2.0),并与声网 API 兼容。