[RedNote] 扫码和 Cookie 均成功后 check_login_status 仍可能误判未登录

Author: Dedean103Created Sep 5, 2026Updated Sep 5, 2026

问题描述

我使用的是 RedNote 海外账号。在本地分支增加 rednote.com backend 后,扫码和 Cookie 持久化已经成功,但 check_login_status 仍曾返回“未登录”。

进一步检查发现:

  • Cookie 文件的修改时间会在扫码确认后更新;
  • .rednote.com 下存在 web_sessionid_token(未修改 Cookie domain);
  • 使用同一份会话调用 search_feeds 可以返回真实结果;
  • 因此至少在这种情况下,扫码和会话本身有效,问题集中在登录状态检测。

相关背景:#609、#699。#812 已经说明 RedNote 获取二维码应使用 /login;本 Issue 主要补充 check_login_status 的假阴性问题。

当前实现的问题

CheckLoginStatus 主要依赖单一 DOM selector:

go
.main-container .user .link-wrapper .channel

RedNote 页面结构、加载时序或前端版本变化时,这个元素不一定能作为稳定的登录证据。Cookie 已经有效的情况下,单一 selector 仍可能导致假阴性。

复现步骤

  1. 使用 RedNote 海外账号,并让浏览器访问 rednote.com
  2. https://www.rednote.com/login 获取二维码;
  3. 在 RedNote App 内扫码并确认;
  4. 确认 Cookie 文件已更新,且存在 .rednote.comweb_session / id_token
  5. 调用 check_login_status,可能仍返回未登录;
  6. 使用相同会话调用只读业务接口(例如 search_feeds),可以正常返回结果。

建议方案

保留原有 selector,同时将 window.__INITIAL_STATE__.user 作为兼容性回退。只有在找到稳定用户身份字段且用户不是 guest 时,才把页面状态判定为已认证:

go
exists, _, err := pp.Has(`.main-container .user .link-wrapper .channel`)
if err != nil {
	return false, errors.Wrap(err, "check login status failed")
}

state, stateErr := readLoginPageState(pp)
if stateErr != nil {
	logrus.Warnf("读取登录页状态失败: %v", stateErr)
}

return exists || (stateErr == nil && state.Authenticated), nil

页面状态读取的核心逻辑:

go
res, err := page.Eval(`() => {
	const unwrap = value => {
		if (!value || typeof value !== "object") return value;
		if (value.value !== undefined) return value.value;
		if (value._value !== undefined) return value._value;
		return value;
	};

	const user = window.__INITIAL_STATE__ && window.__INITIAL_STATE__.user;
	const candidates = user ? [user.userInfo, user.currentUser, user.me] : [];
	const info = candidates
		.map(unwrap)
		.find(value => value && typeof value === "object") || null;

	const guest = Boolean(info && info.guest === true);
	const hasIdentity = Boolean(
		info && (info.userId || info.user_id || info.nickname)
	);

	return JSON.stringify({
		authenticated: Boolean(info && !guest && hasIdentity),
		guest,
		hasIdentity,
	});
}`)

这段读取应保持容错:__INITIAL_STATE__ 或候选字段缺失时,不应该让整个状态检查报错,也不应仅凭状态对象存在就判定登录。

本地验证结果

应用上述兼容检测并重新构建后:

  1. check_login_status 正确返回已登录;
  2. 可以读取当前用户;
  3. search_feeds 在约 5.5 秒内返回真实搜索结果;
  4. 再调用 get_login_qrcode 会提示当前已登录。

脱敏后的诊断日志:

登录诊断: url=https://www.rednote.com/ sidebar=true authenticated_state=true guest=false user_identity=true login_button=false login_modal=false

建议日志只记录上述布尔状态,不输出 Cookie value、token、user id 或昵称。

环境

  • 上游基准 commit:f4518665bbc546aebe3104d78aeb0867af9b720a
  • 账号:RedNote 海外账号
  • 后端:本地分支通过 XHS_BACKEND=rednote 选择 https://www.rednote.com
  • 运行方式:Linux 上的本地二进制服务

如果这个方向符合项目计划,我可以继续把登录状态回退检测整理成独立 PR。

Source: xpzouying/xiaohongshu-mcp