统一身份扩展
2026/10/26大约 2 分钟
统一身份扩展(IdentityService)
系统里一切"能发消息、能被 @ 的主体"都用统一身份 sid 表示:人、群、机器人、未来第三方应用。app\service\IdentityService 负责把一批 sid 批量解析成展示用的最小安全资料,供 IM、@、评论等渲染。
sid 与前缀
sid 由 Hashids 编码,前缀标出主体类型:
| 前缀 | 类型 | 解析归属 |
|---|---|---|
sys_ | 人(系统账号/会员) | 基座内置,读统一主体表 |
grp_ | 群 | 由对应插件注册 provider |
bot_ | 机器人 | 由对应插件注册 provider |
app_ | 应用 | 由对应插件注册 provider |
出口白名单
解析结果只含 sid / type / name / avatar / status / account_type 等非敏感字段,不含 password/salt/email/mobile。插件不应期待从这里拿到敏感资料。
解析(基座/插件调用)
use app\service\IdentityService;
$map = IdentityService::resolve(['sys_xxx', 'grp_yyy']); // [sid => data]
$one = IdentityService::resolveOne('sys_xxx'); // data 或 nullsys_(人)走基座内置解析,带 Redis 缓存、未命中记短 TTL 空占位防穿透。- 未知前缀且没有对应 provider 的 sid 会被安全跳过,不影响其余解析。
注册新前缀的解析器(provider)
插件引入新主体类型(群、机器人等)时,注册该前缀的资料解析器:
use app\basic\AdapterRegistry; // 略
use app\service\IdentityService;
// 写在 boot()
IdentityService::registerProvider(
'grp', // 主体前缀(type)
fn(array $sids): array => RoomService::batchProfile($sids), // [sid => data]
owner: 'am_demo'
);回调签名 fn(array $sids): array,返回 [sid => profile]。
补充已解析条目(extender)
给已经解析出的每条资料追加安全字段(如会员等级、徽章),不改主体结构:
IdentityService::registerExtender(
fn(array $item): array => MemberLevel::attach($item), // 返回合并后的条目
owner: 'am_demo'
);回调签名 fn(array $item): array,逐条应用到 resolve 的每个结果上。
判定与清理
| 方法 | 作用 |
|---|---|
hasProvider($type) | 某前缀是否已注册解析器 |
clearPerson($sid) | 改名/换头像/状态变更后清人员缓存 |
lookupPerson($keyword, $limit) | 按昵称/用户名模糊查人,返回最小展示资料 |
forgetByOwner($owner) | 禁用/卸载时清理 provider/extender(基座自动调用) |
进程级
registerProvider/registerExtender 一律写在 boot(),传 owner。详见生命周期。
