README.md 2.3 KB

桌面长期打开后的 CSRF 自动恢复

基线:主分支 a23f030(v0.4.17)。按用户要求直接在主分支开发。

原因与修改

本地登录 Cookie 有效期为 30 天,CSRF Cookie 为 8 小时。页面一直保留旧的内存令牌;Cookie 到期后,后续写入请求收到 403 invalid_csrf,此前没有自动恢复路径。

统一 API 客户端现在会在缺少令牌时准备令牌,或在收到明确的 403 invalid_csrf 后续领,再重试原请求一次。续领使用 GET /api/app/bootstrap?csrfOnly=1,新服务端仅返回 CSRF 令牌与当前账号 ID,不访问 9119、不加载机器人列表;旧服务端忽略参数后返回的完整 bootstrap 仍可读取。响应禁止缓存。

同一窗口的请求共用一次续领。支持 Web Locks 的同源窗口还会串行签发,避免同时收到两个新 Cookie 相互覆盖;跨窗口令牌通知触发身份核验,而不是直接拿另一窗口的令牌重放操作。

原 Cookie 有效期、签名校验、Origin 校验和登录权限保持原规则。只有业务执行前的明确 CSRF 拒绝才允许重试;网络失败、超时、权限拒绝和一般服务端错误不会自动重试。原请求 ID、请求体和附件保持一致。取消、超时或切换账号后不会重放旧操作。

验证

运行:

bash docs/verification/2026-09-14-desktop-csrf/verify.sh
  • 使用真实 CsrfProtection 签名逻辑及模拟浏览器 Cookie 时钟,将时间推进到 8 小时之后;第一次请求被 CSRF 拦截,自动续领后成功,业务执行计数为 1。
  • 普通聊天、Bot 消息和设置并发时只续领一次;晚到的旧令牌拒绝复用已经更新的令牌。
  • 覆盖旧服务端完整 bootstrap、缺失令牌、续领失败、重复拒绝、网络失败、原请求超时、取消、附件快照和账号切换。
  • 覆盖多窗口 Cookie 签发串行和跨账号令牌通知。
  • 实际 HTTP 路由验证匿名、管理员、普通账号均能续领,且不访问上游;保留既有 Origin、CSRF 和服务重启校验测试。
  • 全部客户端测试及相关服务端测试 66 个文件、378 项通过;类型检查通过。

此次为自动化时钟和协议测试,没有让真实桌面程序等待 8 小时,也没有重启用户服务或更新安装包。结果见 results.txt。