blessing-skin-plugins
blessing-skin-plugins copied to clipboard
[yggdrasil-api] [mojang-verification] uuid 表中数据不一致
问题描述
yggdrasil-api 和 mojang-verification 插件中的多个 bug 会导致 uuid 表中数据一致性被破坏。
1. 多个用户可以绑定同一个正版账户
mojang-verification 插件中,多个不同的用户可以绑定同一个正版账户,这在某些情况下会导致 uuid 表中同一个 uuid 对应多个 name。
重现方法:
- 登录用户 A,绑定正版账户,假设正版角色名称为 alex,此时会在用户 A 下创建一个名为 alex 的角色
- 将用户 A 中与正版账户同名的角色重命名,假设重命名为 bob
- 登录用户 B,绑定同一个正版账户,此时会在用户 B 下创建一个名为 alex 的角色
- alex 与 bob 的 uuid 相同
2. 更新 UUID 未考虑到改名情况
mojang-verification 插件中,更新 UUID 功能在正版角色重命名的情况下,会在 uuid 表中引入 name 不同而 uuid 相同的记录。
重现方法:
- 登录用户 A,绑定正版账户,假设正版角色名称为 alex
- 把正版角色重命名为 bob
- 使用更新 UUID 功能
- uuid 表中,alex 与 bob 的 uuid 相同
3. UUID 生成存在并发安全问题
yggdrasil-api 插件中,getUuidFromName 函数在为新角色生成 UUID 时,会出现并发安全问题,具体表现如下:
- 如使用 version 3 算法,会在 uuid 表中插入多条 uuid 和 name 相同的记录
- 如使用 version 4 算法,会在 uuid 表中插入多条 uuid 不同而 name 相同的记录
以上两种情况,受影响的记录的 id 一般都是相邻的。
4. 多次绑定正版账户导致 uuid 重复
mojang-verification 插件中,在同时多次调用 verifyCallback 时,会出现并发安全问题,进而使得 uuid 表中插入多条 uuid 和 name 相同的记录。
修复建议
- 为 uuid 表中的 uuid 字段、name 字段添加 unique 约束
- 移除 mojang-verification 插件中导入正版 uuid 的功能
- 对现有数据进行修正
- 如果是 uuid 和 name 都相同的记录,保留一条即可
- 如果是 uuid 不同,name 相同的记录,需要确定 hasJoined 接口返回的是哪个 uuid,保留这一 uuid 即可
- 如果是 uuid 相同,name 不同的记录,需要先删除在 players 表中无对应 name 的记录(即此 name 目前未被使用,对应上面第 2 点),如仍有多条记录,则需要具体分析保留哪条记录,这将导致被删除记录的用户游戏数据丢失!
我写了一个脚本 bs-uuid-migration 用来迁移并校验数据,并且会给 uuid 表添加 unique 约束,不过暂时还没有仔细测试。