定时任务里 SPA 登录态的"假掉线":页面说没登录,接口却照样 200 的一次排查

举报
yd_297054392 发表于 2026/11/02 21:44:26 2026/11/02
【摘要】 无人值守任务里,页面显示「登录/注册」但后端接口照样 200——一次真实排查,讲清 SPA 头部渲染、匿名可读接口、会话级 cookie 与设备信任的区别,以及为什么不能用瞬时余额判断任务是否到账。附一张登录态与入账判据清单。

定时任务里 SPA 登录态的"假掉线":页面说没登录,接口却照样 200

一次无人值守任务的真实排查:如何区分"页面没渲染"“会话过期”"接口匿名可读"这三件完全不同的事。

一、现象:两个信号互相打架

有个每天定时跑的任务,负责登录某云开发者社区、签到并推进成长任务。某天打开成长中心页,右上角是「登录/注册」,积分块显示 -,连续签到天数也是 -。按直觉这就是掉登录了。

但在同一个浏览器里,带着 cookie 去请求后端任务列表接口:

POST https://devdata.huaweicloud.com/rest/.../growth/mission/query-mission-list-by-condition
{"page_no":1,"page_size":50,"category_key":"DAILY_MISSIONS"}

返回 HTTP 200、total: 12、12 条任务一条不少。页面说没登录,接口说登录着——到底信谁?

结论先放:这两个信号描述的不是同一件事,都不能单独当作登录态判据。真正的判据是"访问一个必须登录的页面,看它跳不跳认证页"。

二、SPA 头部不渲染账号名,不等于掉登录

现代社区站点大多是前后端分离的 SPA:顶部导航是通用组件,登录态由一套独立的账号 SDK 异步注入。在 headless Chrome 里,document.visibilityState 常为 hidden,React 组件不会 hydrate,或者账号 SDK 的异步回调没跑完——这时头部就停在"登录/注册"的默认态,积分块也停在骨架屏的 -。

也就是说:页面显示「登录/注册」,可能只是前端没渲染完,也可能是真掉登录。

修复 hydration 本身有标准做法(CDP 里每次导航后重设):

cdp('Emulation.setFocusEmulationEnabled', enabled=True)
cdp('Page.setWebLifecycleState', state='active')

置成 visible 后再等几秒重读。但要注意:这次我把 visibilityState 修成 visible 后,积分块仍然是 -——说明这次不是 hydration 问题,是真掉登录了。所以"页面文案"连反向推断都不可靠。

三、接口 200 也不等于登录着

另一个坑是把"接口能返回数据"当成"会话还有效"。这类查询接口常常是匿名可读的:奖品库存、任务列表、7 天签到奖励表,不带登录态也能拿全量数据。本次实测的 growth/sign 接口返回:

{"sign_invo_list":[{"count":1,"bonus":10}, {"count":7,"bonus":10}]}

只有一张规则表,没有任何"当前用户今天签没签"的字段。想靠它判断签到状态行不通。

所以:接口 200 / total>0,只证明接口通、参数对,不证明会话有效。

真正的会话态判据,是访问一个必须登录才能进的页面并观察跳转:

https://bbs.huaweicloud.com/blogs/article(写博客页)
  → 302 到 auth.huaweicloud.com/authui/login.html?...  = 真掉登录
  → 停在原页、编辑器渲染出来                          = 仍登录

这次导航过去,地址栏落到 auth.huaweicloud.com/authui/login.html?service=...,实锤掉登录。

四、为什么会掉:会话 cookie 与设备信任是两回事

账号体系里至少有两类 cookie:

  • 设备信任标记(如 vk),有效期 365 天,作用是"这台机器免二次验证/免短信码";
  • 真正的会话 cookie,是会话级的,浏览器进程一重启就失效。

无人值守任务用的是常驻 headless Chrome(systemd 用户服务托管、profile 落在磁盘上)。某次服务重启或崩溃重拉后,profile 里的长有效期 cookie 还在,但会话 cookie 没了——于是页面回到"登录/注册"。这不是"信任设备失效",也不是"固定浏览器没生效",只是会话级 cookie 的正常生命周期。

重登流程也因此很轻:切到「密码登录」标签 → 填账号 → 由本地凭据库注入密码 → 点登录。因为设备信任仍在,不会弹 6 位短信码,直接跳回目标页。登录完成后回到成长中心,账号名、积分、签到天数一次性全部渲染出来。

顺带一个易踩的细节:在页面里调后端写接口要带 csrf 头,值必须取自 GET /api/get-ainfo 的响应头,不能用 cookie 里那个 csrf-eco 的值,否则报 no request_csrf found。

五、别用"当时的余额"判断任务有没有到账

这次还顺带纠正了一个误判。凌晨的推进任务提交了提 Issue,90 秒后积分余额仍是 920,于是记了"60 分尚未到账,下次再核"。晚上复核积分明细流水:

2026/11/02 03:22  签到第7天   +10   → 920
2026/11/02 03:24  提 Issue    +60   → 980

分其实是当场到账的,凌晨那次读到的 920 是签到之后的中间态,Issue 的入账恰好错开了那个采样点。类似地,云实验任务常见"开完环境余额不动,半小时后批处理才 +50"。

所以判"有没有得分"的可靠顺序是:

  1. 积分明细流水(带时间、来源、变动前后余额)优先于当时余额;
  2. 一次性动作(Star、提交)看业务侧证据:按钮变 Starred 且网络里出现 POST .../star 而不是 .../unstar,仓库 Issues 计数 +1 且作者对得上;
  3. 接口里的 is_finish 只能作参考——多数任务恒为 0,个别周任务完成会真实变 1,它能证明"已到账",不能证明"未完成"。

六、小结:一张判据清单

现象 能推出 不能推出
页面显示「登录/注册」 前端可能没 hydrate 会话一定失效
查询接口 200 / total>0 接口通、参数对 已登录
必须登录页 302 到 auth 真掉登录 —
瞬时余额没涨 采样时刻的状态 任务失败
is_finish = 0 无 任务未完成
积分明细出现 +60 行 已到账 —

无人值守任务最怕的不是"做失败",而是"把状态判错"后反复重试、甚至误判成需要人工介入。把"页面文案 / 接口可达 / 会话有效 / 入账流水"这四层状态分开验证,各用各的判据,比盯着一个数字猜要稳得多。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。