保存独立KV用户服务、固定会话存档与原业务接线,以及C3d资料缓存和C3e本人统计写。 保留原PF/AGG路线、业务公式和时序;榜单读取、好友资料、公告、匹配及首场景闸仍待完成。 验证:ServiceHost两条件各33组646断言;Unity CLI Loop编译0错误269警告。 包含相关方案、评审裁决、测试及状态文档。未操作服务器、正式账号或打包。
118 lines
7.8 KiB
Markdown
118 lines
7.8 KiB
Markdown
# M2 CP2B-T独立方案审查:正式KV普通业务请求恢复(含第6–8项补审)
|
||
|
||
日期:2026-09-29。审查者:ZCode会话(M2全链审查者)。本轮只读+hash重算+源码核对。
|
||
|
||
## 受审hash核对
|
||
|
||
`M2-CP2B-T受审基线.json`:**7/7全部一致**。
|
||
|
||
## 总裁决
|
||
|
||
**通过。** 可批准CP2B-T实施(主会话裁决后)。无P1/P2;P3三条不阻塞。
|
||
|
||
## 五问逐答
|
||
|
||
### 1. 同一Context租约与运输就绪时序:**闭合**
|
||
|
||
- 正式模式通过`PlayerKVAccountLease`扩展(区别于验证两路由),复用同一CookieContainer与Close排水——无第二HttpClient、无第二登录;
|
||
- **运输就绪时点正确定义为CP3A三原实例交接后**——不是Apply前(`BindKVForGame`时仍标未就绪),也不是GameLoaded即刻(须等CP3A绑定成功)。这防止了加载期间业务副作用;
|
||
- 路线B正确(A丢所有权/C新增第四传输面)。
|
||
|
||
### 2. 路径校验与专用路由保护:**充分**
|
||
|
||
- 规范相对路径校验列表全面(空/绝对/跨源/`//`/`?`/`#`/`%`/控制字符/`.`/`..`);
|
||
- **保留`__kv_validation/*`、`account/Login`、`playerdata/*`拒绝**——防绕过验证路由/重认证/绕过专用KV传输;
|
||
- "不能以'只列Mail/Friend'再造临时禁用门"——正确的避免碎片化门控原则;
|
||
- 方案诚实声明"客户端路由字符串不冒充线上响应合同"——运输可用≠线上验证。
|
||
|
||
### 3. 401/Logout/旧响应闭合:**闭合**
|
||
|
||
- 401/403→同步撤销就绪+身份+原handle→再交Coordinator关闭——与CP2A/CP3A撤销顺序一致;
|
||
- Logout/Quit→任何await前同步禁用+递增SessionVersion→租约排水——正确时序;
|
||
- 旧响应不发布/不覆盖新身份——同epoch检查;
|
||
- **`UserService.cs`不在白名单能否只靠`UserService.KVLoad.cs`完成**:**能**——401事件处理/Logout逻辑/EnableKVBusiness调用均可在此文件实现,不需要改`UserService.cs`的公开签名或构造。
|
||
|
||
### 4. 合成独立验收:**可行且充分**
|
||
|
||
- 合成handler可完整验证:就绪前零发送→就绪后正常路径发送→验证租约仍限两路由→路径校验→401/退出/旧epoch→Cookie/SessionVersion;
|
||
- **不能证明的**(方案如实声明):线上响应合同、公开身份发布、真实Player编译、SignalR真实连接——均留后续。
|
||
|
||
### 5. 白名单/回归/闲置清理:**足够**
|
||
|
||
3文件白名单精确到方法/入口。无新增闲置接口——`EnableKVBusiness`由UserService.KVLoad消费、租 lease扩展由CustomServerMgr消费、Cookie交接由RTService将来消费(G5)。最终清账在CP4/5统一。
|
||
|
||
## P3
|
||
|
||
- **P3-1**:§3.5的`Cookie`对RTService开放——建议实现时在Cookie返回前加日志("Formal KV Cookie released to RTService")便于G5 SignalR连接调试时追踪;
|
||
- **P3-2**:§3.1的路由校验建议用一个`static readonly HashSet<char>`或类似结构表达禁止字符集,防实现时遗漏;
|
||
- **P3-3**:§5验收用例中建议加"验证租 lease尝试发送普通业务路径被拒绝"的显式断言(方案已隐含,落为独立用例更清晰)。
|
||
|
||
## 结论
|
||
|
||
**通过CP2B-T方案。** 主会话核hash(已代验7/7)裁决后按3文件白名单实施。这是打通"正式业务API可用"的关键一步——CP2B首场景/身份发布/SignalR留后续。
|
||
|
||
---
|
||
|
||
## 第6–8项补审(同批追加,与原五项合并裁决)
|
||
|
||
### 6. formal/validation模式传递与路径/超时兼容
|
||
|
||
**模式传递安全**:`PlayerKVControlledLoadCapability`已有`readonly bool formal`字段(:339–340),构造时固定。`PlayerKVAccountLease`可通过同一capability获取`formal`标志来区分路由策略:
|
||
- 验证模式→仅两精确路由(原语义不变)
|
||
- 正式模式→规范相对路径,但**拒绝**`__kv_validation/*`(防验证入口暴露于正式)+拒绝`account/Login`+`playerdata/*`(保持专用传输)
|
||
- 三向隔离闭合
|
||
|
||
**已知合法调用误拒风险**:源码核实`CustomServerMgr.cs:124`使用`Timeout = TimeSpan.FromSeconds(15)`。方案要求租约保持此超时。当前`PlayerKVLoginContext`中lease的HttpClient尚未设置显式Timeout——**P3级:实施时须为正式模式lease的HttpClient设置15秒超时**(与旧CustomServerMgr一致)。超时返回空结果/错误事件,不误判为401。
|
||
|
||
**`?`查询参数**:方案§3.1拒绝`?`——但现有业务调用如`mail/fetch`可能含查询参数。**P2级:需在实施前核查全部现有`CustomServerPost`/`GetStringAsync`调用点的实际路径模板**,确认无`?`形式的合法调用被误拒。如有,最小修订为允许`?`后的有效字符但拒绝`%`/`#`。
|
||
|
||
**结论**:模式传递安全;超时需补设置(P3);路径校验需核查`?`兼容(P2)。
|
||
|
||
### 7. GameLoaded后发布运输就绪时的实际调用者
|
||
|
||
**这是"普通请求运输可用"而非"首场景业务可用"**——方案已明确。
|
||
|
||
源码核实(`UserService.cs:110`):`IsLogin => !kvControlledInstance && !IsFormalKV && PlayFabClientAPI.IsClientLoggedIn() && IsAuthorized`。正式KV下`IsFormalKV=true`→`IsLogin`恒false→`ApiPlayerId`(依赖`IsAuthorized`即`apiSession!=null`)也为null。
|
||
|
||
**实际调用者风险**:
|
||
- `PFLoginAct`停在登录页(CP2A双闸)→不会自动发业务请求
|
||
- `FishingStage`被LoginStage阻断→Mail/Survey/排行榜/Friend等不可达
|
||
- **但**:任何后台协程/事件订阅可能通过`CustomServerMgr.CustomServerPost`发送请求——CP2A已排除PF组件和旧回调
|
||
|
||
**结论**:三文件白名单**足够**。`IsLogin`/`ApiPlayerId`的正确身份发布属CP2B(首场景),本批仅开放运输层。当前无实际调用者会提前发请求——阶段闸保障了这一点。
|
||
|
||
### 8. Cookie/SignalR失效与Close双重关闭
|
||
|
||
**RTService消费核实**(:69–77):
|
||
```csharp
|
||
var session = _serverMgr.SessionVersion;
|
||
var cookies = _serverMgr.Cookie;
|
||
// ... version/session检查 → new HubConnectionBuilder().WithUrl(..., option => option.Cookies = cookies)
|
||
```
|
||
RTService在Connect时读取Cookie和SessionVersion,每次连接前核版本——SessionVersion递增后旧连接的`CloseConnection()`+新Connect用新Cookie。**失效路径成立**。
|
||
|
||
**双重Close风险**:
|
||
- `PlayerKVAccountLease.CloseAsync`负责租 lease级排水
|
||
- `CustomServerMgr`可能也调用清理
|
||
- 方案§3.4已明确"任何await前同步禁用普通请求、递增SessionVersion、触发SessionChanged"——**同步禁用先于任何异步操作**,不存在双关窗口
|
||
- Close幂等(4A合同已验证)
|
||
|
||
**401回调线程**:`CustomServerMgr.SendAsync`在HttpClient响应后调用事件——回调可能在.NET线程池非主线程执行。`LogoutFormalKV`的同步撤销部分(禁用businessReady/清handle)不涉及锁内await,可安全从任何线程执行。后续Coordinator关闭(含await)应在主线程或配合同步上下文调度——**P3级:建议实施时在401处理中用`SynchronizationContext.Post`或等效方式调度到主线程**。
|
||
|
||
**旧响应撤销新会话**:SendAsync返回后核"响应仍属同租约/版本/epoch"——方案§3.3已覆盖。
|
||
|
||
**结论**:三文件白名单**足够**,不需要改RTService.cs或UserService.cs。401回调线程需注意调度(P3)。
|
||
|
||
---
|
||
|
||
## 更新后总裁决
|
||
|
||
**通过(维持原裁决,附加一项P2和三项P3)**:
|
||
|
||
- **P2-1**:实施前核查全部现有`CustomServerPost`/`GetStringAsync`调用点的路径模板,确认方案§3.1的路径校验(含`?`拒绝)不误拒已知合法调用。
|
||
- **P3-1**:正式模式lease的HttpClient须设置15秒超时(与旧CustomServerMgr:124一致)。
|
||
- **P3-2**:401回调建议调度到主线程后执行撤销。
|
||
- **P3-3**(原P3-3保留):验证租 lease拒普通路径的独立断言。
|
||
|
||
原五项结论不变。三文件白名单确认足够。"无线上业务合同也能独立实施运输层、同时阻断FishingStage"**成立**。
|