From ab4c0a5422c3bb8db26046d4ebc4f949b6c114a7 Mon Sep 17 00:00:00 2001 From: yml2213 Date: Mon, 5 Oct 2026 18:20:10 +0800 Subject: [PATCH] =?UTF-8?q?fix(login):=20=E9=87=8D=E7=99=BB=E6=88=90?= =?UTF-8?q?=E5=8A=9F=E5=90=8E=E6=8A=8A=20CK=20=E6=A3=80=E6=B5=8B=E7=BB=93?= =?UTF-8?q?=E8=AE=BA=E5=86=99=E5=9B=9E=E8=B4=A6=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 登录凭据快照盖掉了 ORM 账号,on_ck_verdict 读不到 ck_check_status,新 Cookie 被丢掉。 Co-authored-by: Cursor --- tests/test_login_attempt_isolation.py | 32 +++++++++++++++++++++++++++ web/backend/services/login_service.py | 8 +++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/tests/test_login_attempt_isolation.py b/tests/test_login_attempt_isolation.py index 196327b..b156302 100644 --- a/tests/test_login_attempt_isolation.py +++ b/tests/test_login_attempt_isolation.py @@ -7,6 +7,7 @@ 停止、失败、进程重启都不可能破坏账号已有的 CK。 """ +from datetime import UTC, datetime from types import SimpleNamespace from sqlalchemy.orm import sessionmaker @@ -171,6 +172,37 @@ class TestLoginAttemptIsolation: assert account.cookie_updated_at is not None assert account.cookie_source == "web" + def test_relogin_success_writes_ck_verdict_on_the_account(self, monkeypatch): + """重登成功后的复检必须写到账号上,不能写到登录器的临时对象上。 + + 2026-10-05 生产:登录已经成功,但 `on_ck_verdict` 收到的是 + SimpleNamespace,读 `ck_check_status` 抛异常,新 Cookie 被丢弃, + 页面上全部是「重新登录异常(旧 Cookie 已保留)」。 + """ + self.account.ck_check_status = "invalid" + self.session.commit() + monkeypatch.setattr( + login_service, + "check_douyu_cookie", + lambda _cookie: { + "valid": True, + "message": "ok", + "fish_ball": 1, + "nickname": "n", + "level": 1, + "checked_at": datetime.now(UTC), + }, + ) + + self._run_batch(monkeypatch, mode="relogin") + + task = self._fresh(self.task_id) + account = self._fresh_account() + assert task.attempt_status == "success" + assert "SimpleNamespace" not in (task.attempt_message or "") + assert account.cookie == "new-cookie" + assert account.ck_check_status == "valid" + def test_stopped_batch_keeps_existing_cookie(self, monkeypatch): self._run_batch(monkeypatch, stop=True) diff --git a/web/backend/services/login_service.py b/web/backend/services/login_service.py index 19fd360..cd7ce1e 100644 --- a/web/backend/services/login_service.py +++ b/web/backend/services/login_service.py @@ -412,7 +412,11 @@ class LoginBatchRunner: ) return - account = cast( + # 只给登录器用的凭据快照。不能覆盖上面的 ORM `account`: + # 重登成功后 `on_ck_verdict` 要写账号的 ck_check_*, + # SimpleNamespace 没有这些字段,会把整次成功登录判成异常, + # 新 Cookie 也就写不回去。 + login_account = cast( AccountLike, SimpleNamespace( username=acc_info["username"], @@ -426,7 +430,7 @@ class LoginBatchRunner: ) loginer = DouyuLogin( - account, + login_account, proxy=proxy_dict, max_login_retries=self.max_login_retries, max_total_time=self.max_total_time,