权限与安全模型
小程序的能力全部靠权限控制:manifest 声明 → 用户安装时授权 → 后端每次请求校验。
权限一览
| 权限 | 能做什么 | 不能做什么 |
|---|---|---|
profile.read | 读取调用者自己的用户名与头像 | 看不到任何别人的资料 |
chat.read | 读取当前会话的成员与最近消息(上限 100 条) | 不能读取其它会话,不能读取历史全量 |
message.send | 以调用者名义向当前会话发文本(每分钟 ≤ 10 条) | 不能发文件/图片,不能改别人的消息,不能代别人发言 |
kv.read | 读取自己在本命名空间下的数据 | 读不到别的命名空间 / 别的小程序 |
kv.write | 写入、删除自己在本命名空间下的数据 | 同上;且受配额限制 |
没有声明的权限,安装界面里根本不会出现;声明了但用户没勾选,运行时会被拒绝。
授权流程
- 用户在商店里点开某个小程序 → 详情页列出 manifest 声明的全部权限(默认全勾);
- 用户按需取消勾选 → 点「安装」(个人)或「添加到本群」(群);
- 平台把勾选结果写入安装记录;
- 之后每次请求,后端用安装记录里的权限做校验。
授权可以随时调整:「已安装 → 改授权」。改授权只会在 manifest 声明的范围内生效,用户不能凭空赋予未声明的权限。
群安装是谁的权限?
小程序装在群里时,授权记录属于这个群(不是某个成员)。 任何群成员调用它,都受同一份授权约束;它代发的消息以调用者的名义发出,而不是安装者。
后端怎么校验
- 每个
/api/mini/*请求都会先解析出「哪条安装记录」(appId + 作用域),再校验调用者能不能用它:- 群作用域:调用者必须是该群成员;
- 个人作用域:必须是本人。
- 然后校验这项操作需要的权限是否在授权记录里,不在就返回
api.mini.noPerm(403)。 - 前端 SDK 也会先查一遍权限,但那只是为了少发一次无效请求,真正的校验在后端。
令牌的作用域限制
沙箱里的直连请求带 X-Mini-Token。令牌由会话派生,内容里写死了:
{ u: 用户名, a: appId, s: 作用域, c: scopeId, p: 已授权权限, exp: 过期时间 }服务端据此做了三重约束:
- 只对
/api/mini/*生效:拿它调/api/me、发普通消息等,一律 401; - appId 必须一致:请求里带别的 appId(哪怕是已安装的另一个)直接 403;
- 作用域固定:令牌绑定
user或某个group,不能跨作用域访问。
令牌有效期 1 小时,用 HMAC-SHA256 签名,密钥存在服务端的整站配置里(首次使用时自动生成)。 它不是用户可以创建、查看、轮换的 API Key。
安装 / 卸载类操作
安装、卸载、改授权只接受会话 Cookie,不接受令牌:这些是用户行为,不该由沙箱里的小程序触发。
其它限制
| 限制 | 值 |
|---|---|
| 代发消息频率 | 每个「用户 + 小程序」每分钟 10 条 |
| 单次读取消息条数 | 最多 100 |
| 单条消息正文 | 4096 字符 |
| KV 键长 | 256 字节 |
| KV 单值大小 | 64 KB |
| KV 键数量 / 总容量 | 每命名空间 500 个键 / 1 MB |
| 索引文件 | 1 MB,单源 200 个 app,合并后 500 个 |
| 索引拉取超时 | 5 秒 |
沙箱边界
iframe 固定使用 sandbox="allow-scripts":
- 不透明源 → 拿不到 Cookie、读不到宿主 DOM;
- 不能弹窗、不能顶层跳转、不能下载、不能使用需要用户手势之外的敏感 API;
- 不能访问同源存储(
localStorage属于不透明源,且随时可能被清掉)——需要持久化就用CircleChat.kv。
关于第三方源
索引源由部署者配置,平台信任管理员填写的地址,但不会把会话 Cookie 或令牌发给第三方服务器:
- 索引是服务端拉取的(或浏览器跨域 fetch,不带凭据);
- 小程序页面里没有令牌,令牌只在运行时由宿主通过 postMessage 下发;
- 页面里的脚本仍然运行在沙箱中,只能调
/api/mini/*,且受授权约束。
管理员只应添加可信的第三方源——就像只应安装可信的软件。
审计
以下动作会写入审计日志,可在「管理面板 → 日志」按「小程序」类别筛选:
| 动作 | 说明 |
|---|---|
mini.install | 安装小程序(区分个人 / 群) |
mini.uninstall | 卸载小程序 |
mini.regrant | 修改授权 |
mini.invoke | 通过 #指令 调用 |
mini.msg | 小程序代发消息(记前 40 字) |
mini.sourceConfig | 管理员修改索引源 |