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:
1 parent
7b305b0b12
commit
9feb188d93
3 files changed
+46
-30
No files matched your search
@@ -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",
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in new issue
Block a user