fix(cookie-gate): 必需 cookie 改全量校验并收紧各账号必需名单

required_cookie_names 原语义是「任一必需名命中即有效」,单个匿名 cookie
(如小红书 a1)就能把游客会话判为有效;改为全部必需名都存在、存活且域名
匹配才算通过。随之按实际登录产物收紧名单:jd 去 pin、erp321 留
u_id+u_co_id、小红书改 customer-sso-sid+solar.beaker.session.id、
星图仅 sid_guard。cookie_gate 用例冻结时钟改相对时钟防过期漂移。
This commit is contained in:
wangyunlong committed 2026-10-14 18:38:03 +08:00
1 parent 7b305b0b12
commit 9feb188d93
3 files changed
+46 -30

No files matched your search

+10 -14
View File
@@ -88,7 +88,6 @@
"jd.com"
],
"required_cookie_names": [
"pin",
"thor"
],
"credential_env_names": [
@@ -116,7 +115,6 @@
"jd.com"
],
"required_cookie_names": [
"pin",
"thor"
],
"credential_env_names": [
@@ -145,10 +143,7 @@
],
"required_cookie_names": [
"u_id",
"u_co_id",
"ASP.NET_SessionId",
".ASPXAUTH",
"token"
"u_co_id"
],
"credential_env_names": [
"ERP_USERNAME",
@@ -299,7 +294,8 @@
"xiaohongshu.com"
],
"required_cookie_names": [
"web_session",
"customer-sso-sid",
"solar.beaker.session.id",
"a1"
],
"keepalive": {
@@ -351,9 +347,6 @@
"xingtu.cn"
],
"required_cookie_names": [
"sessionid",
"sessionid_ss",
"sid_tt",
"sid_guard"
],
"keepalive": {
@@ -365,8 +358,7 @@
"headless": true,
"real_chrome": true
},
"members": [
]
"members": []
},
"chanmama": {
"cdp_port": 22207,
@@ -702,8 +694,12 @@
],
"cdp_port": 22165,
"login_mode": "C",
"required_cookie_domains": ["xiaohongshu.com"],
"credential_env_names": ["XHS_ARK_ACCOUNT"]
"required_cookie_domains": [
"xiaohongshu.com"
],
"credential_env_names": [
"XHS_ARK_ACCOUNT"
]
},
"content_marketing:data/tools/sync_style_categories.py": {
"script_id": "content_marketing:data/tools/sync_style_categories.py",
+35 -15
View File
@@ -1210,29 +1210,49 @@ def _merge_storage_state(
def _account_cookie_valid(account: AccountBinding, cookies: object) -> bool:
"""A vault cookie set is valid when a live account cookie is present."""
"""A vault cookie set is valid when a live account cookie is present.
With ``required_cookie_names`` configured, every required name must be
present as a live, domain-matched cookie; a single anonymous cookie that
happens to share a required name (e.g. ``a1``) must not validate a guest
session. Without required names, any live cookie on a required domain
keeps accepting the set.
"""
if not isinstance(cookies, list):
return False
required_names = account.required_cookie_names
required_domains = account.required_cookie_domains
for item in cookies:
if not isinstance(item, dict):
continue
if _cookie_expired(item):
continue
if not str(item.get("value", "")):
continue
name = str(item.get("name", ""))
domain = str(item.get("domain", "")).casefold().lstrip(".")
name_matches = not required_names or name in required_names
domain_matches = not required_domains or any(
def _domain_matches(domain: str) -> bool:
return not required_domains or any(
domain == required.casefold()
or domain.endswith("." + required.casefold())
for required in required_domains
)
if name_matches and domain_matches:
return True
return False
def _live(item: object) -> bool:
return (
isinstance(item, dict)
and not _cookie_expired(item)
and bool(str(item.get("value", "")))
)
if not required_names:
return any(
_live(item)
and _domain_matches(
str(item.get("domain", "")).casefold().lstrip(".")
)
for item in cookies
)
outstanding = set(required_names)
for item in cookies:
if not _live(item):
continue
if _domain_matches(str(item.get("domain", "")).casefold().lstrip(".")):
outstanding.discard(str(item.get("name", "")))
return not outstanding
def _cookie_expired(cookie: Mapping[str, object], *, now: float | None = None) -> bool:
+1 -1
View File
@@ -28,7 +28,7 @@ from gyxx_flow.workflow.engine import WorkflowEngine
from gyxx_flow.workflow.model import StepDefinition, WorkflowDefinition
from gyxx_flow.workflow.steps import StepExecution
_NOW = datetime(2026, 10, 8, 12, 0, 0, tzinfo=timezone.utc)
_NOW = datetime.now(timezone.utc).replace(microsecond=0)
def _settings(tmp_path: Path) -> Settings: