平台说明
浏览器登录态设计
基于 Auth State 的浏览器登录态架构说明
1. 背景
旧版浏览器登录态主要依赖用户 base profile 复制到会话 profile。在以下场景下,容易出现“已登录后再次对话仍需重登”或“旧状态覆盖新状态”:
- 浏览器实例在同一容器内被关闭并重新拉起,CDP 上下文变化。
- 会话容器被回收后重建,profile 复制时机与浏览器写盘时机不一致。
- 多运行实例并发读写 profile,存在文件级时序覆盖。
- 用户在远程浏览器手动登录后,任务浏览器是否继承登录态依赖 profile 是否已经稳定落盘。
当前实现已废弃“用户 base profile 复制会话 profile”方案,将用户登录态提升为 Backend 管理的逻辑状态。
2. 目标与范围
2.1 目标
- 以用户级 Auth State 作为唯一持久化真相源。
- 废弃任务启动时的用户 base profile 复制机制。
- 支持远程浏览器手动登录后,后续任务浏览器稳定复用登录态。
- 支持任务浏览器登录后,后续远程浏览器也能恢复登录态。
- 支持同容器浏览器重启后的自动恢复。
- 支持多运行实例并发提交时的一致性合并。
2.2 范围
- 当前稳定支持内置 Playwright MCP / CDP 浏览器链路。
agent_browser已接入同一套 Auth State hook,但仍属于受限/实验链路;涉及登录态复用的任务优先使用 Playwright MCP。- 当前仅覆盖
Cookie + localStorage。 - 不新增独立容器服务。
- 不引入站点白名单与多策略切换。
- 不覆盖 IndexedDB、ServiceWorker、CacheStorage、sessionStorage、浏览器缓存、完整 Chrome profile。
3. 设计原则
- 单一真相源:Backend Auth State 是唯一长期保存登录态的位置。
- 低侵入:仅在远程浏览器边界、任务会话边界、浏览器工具调用边界插入逻辑。
- 低耦合:Backend/Executor Manager/Executor 各自职责单一。
- 明确语义:导出状态必须区分“未观测”与“显式删除”,避免误删。
- 易扩展:后续可在同模型上扩展 IndexedDB、ServiceWorker、CacheStorage 等状态类型。
4. 总体架构
4.1 组件职责
- Backend:加密存储用户级 Auth State,提供快照读取、版本提交、清空接口,执行并发合并。
- Executor Manager:在远程浏览器和任务浏览器边界同步 Auth State,负责快照落盘与终态提交。
- Executor:通过 CDP 注入/导出浏览器状态,在浏览器重启时自动再注入。
4.2 核心思路
- 远程浏览器启动:拉取 Auth State 并注入浏览器。
- 远程浏览器停止/删除/任务启动前:导出远程浏览器当前状态并提交 Backend。
- 任务启动:拉取最新 Auth State 快照并写入会话工作区。
- 任务运行:浏览器工具调用前后通过 CDP 做注入、导出和自愈。
- 任务结束:导出最终状态并提交 Backend,按版本合并。
4.3 与旧 profile copy 的关系
- 不再从用户 base profile 复制到会话 profile。
- 任务容器使用容器内
/tmp/poco-task-browser-profile作为临时浏览器 profile。 - 远程浏览器使用容器内
/tmp/poco-remote-browser-profile作为临时浏览器 profile。 - 远程浏览器和任务浏览器之间的登录态传递只通过 Backend Auth State 完成。
- 旧的历史 profile/cache 目录不再作为兼容路径参与读写,也不再作为登录态清理目标。
5. 数据模型(Backend)
新增表:user_auth_states
tenant_id(varchar, PK)user_id(varchar, PK)schema_version(int, not null)version(bigint, not null)cleared_at_version(bigint, not null)encrypted_state(text/jsonb, not null)updated_by_run_id(varchar, nullable)updated_at(timestamp with time zone, not null)
说明:
encrypted_state保存加密后的 Auth State,不裸存 Cookie/localStorage token。- 加密密钥通过 Backend 配置管理,不下发到 Executor 或 Executor Manager。
tenant_id + user_id作为隔离边界,内部接口不得通过 query 参数任意指定其他用户。
解密后的 Auth State 结构:
{
"cookies": [
{
"name": "sid",
"value": "...",
"domain": ".example.com",
"path": "/",
"expires": 1767225600,
"httpOnly": true,
"secure": true,
"sameSite": "Lax"
}
],
"local_storage": {
"https://example.com": {
"token": "...",
"user_id": "123"
}
},
"observed_scopes": {
"cookie_domains": [".example.com"],
"local_storage_origins": ["https://example.com"]
},
"tombstones": {
"cookies": [
{
"name": "sid",
"domain": ".example.com",
"path": "/"
}
],
"local_storage": [
{
"origin": "https://example.com",
"key": "token"
}
]
}
}6. 内部接口(Backend)
所有接口必须使用内部鉴权:
X-Internal-TokenX-User-IdX-Tenant-Id(若当前系统已有统一 tenant 来源,可复用现有上下文)
6.1 读取快照
GET /api/v1/internal/auth-state/snapshot
返回:
{
"tenant_id": "default",
"user_id": "u1",
"version": 12,
"schema_version": 1,
"state": {
"cookies": [],
"local_storage": {},
"observed_scopes": {
"cookie_domains": [],
"local_storage_origins": []
},
"tombstones": {
"cookies": [],
"local_storage": []
}
}
}6.2 提交状态
POST /api/v1/internal/auth-state/commit
请求:
{
"base_version": 12,
"base_state": {},
"new_state": {},
"run_id": "run_123"
}返回:
{
"tenant_id": "default",
"user_id": "u1",
"version": 13,
"schema_version": 1,
"state": {}
}6.3 清空状态
DELETE /api/v1/internal/auth-state
用于“清空远程浏览器数据”时同步清空 Auth State。
7. 关键时序
7.1 远程浏览器启动
- Backend
remote-browser/start代理到 Executor Manager。 - Executor Manager 启动或复用用户远程浏览器容器。
- Executor Manager 调 Backend
snapshot获取最新 Auth State。 - Executor Manager 通过远程浏览器 CDP 注入
Cookie + localStorage。 - 远程浏览器容器继续作为用户交互入口运行。
7.2 远程浏览器停止
- Executor Manager 先通过 CDP 导出远程浏览器当前状态。
- 调 Backend
commit(base_version, base_state, new_state)。 - 停止 Chrome,停止远程浏览器容器。
- 远程浏览器 profile 可保留为运行缓存,但不能作为长期真相源。
7.3 远程浏览器数据删除
- Executor Manager 停止远程浏览器容器。
- 调 Backend
DELETE /api/v1/internal/auth-state清空 Auth State。 - 清理远程浏览器本地 baseline 文件,避免后续 flush 继续基于旧基线生成删除语义。
- 不再清理历史 profile/cache 目录;这些目录不是当前登录态真相源。
7.4 任务启动
- Executor Manager 判断
browser_enabled=true。 - 若用户远程浏览器容器正在运行,先导出并提交一次远程浏览器状态。
- 调 Backend
snapshot获取{version, state}。 - 将快照写入会话工作区:
/workspace/.poco/auth-state/base.json。 - 创建任务容器,使用容器内临时 Chrome Profile,不执行用户 base profile copy。
- Executor 启动后等待 CDP ready,并注入
base.json。 - 初始化
working_state。
7.5 任务运行(浏览器重启自愈)
- 浏览器工具调用前,Executor 检查当前浏览器实例指纹,例如 CDP version、webSocketDebuggerUrl、target id 组合。
- 若浏览器实例变化,立即使用
working_state执行再注入。 - 浏览器工具调用后,导出当前
Cookie + localStorage,刷新working_state。 - 导出失败只记录错误,不生成删除语义。
7.6 任务结束
- Executor teardown 阶段导出最终状态。
- Executor 将最终状态写入:
/workspace/.poco/auth-state/final.json。 - Executor Manager 收到 terminal callback 后读取
base.json与final.json。 - 调 Backend
commit(base_version, base_state, new_state)。 - Backend 合并并返回最新版本。
- Executor Manager 清理
.poco/auth-state工作文件。 - Ephemeral 任务容器按现有逻辑停止,profile 不再参与持久化。
8. 并发一致性(合并规则)
采用三方合并:base_state、current_state(库内最新)、new_state(本次提交)。
- Cookie 主键:
(name, domain, path)。 - localStorage 主键:
(origin, key)。
规则:
new相对base未变:保留current。new相对base有变:应用new。- 删除必须来自
tombstones,不能用“缺失”推断删除。 - 只有在
observed_scopes内的 Cookie domain 或 localStorage origin 才允许产生 tombstone。 - 未观测到的 domain/origin/key 不参与删除。
- 合并完成后
version = version + 1。
该策略避免旧运行实例整包覆盖新运行实例状态,也避免因导出范围不足误删其他站点登录态。
9. CDP 注入与导出规则
9.1 Cookie
- 注入:使用 CDP
Network.setCookies。 - 导出:使用 CDP
Network.getAllCookies。 - 过滤已过期 Cookie。
- 保留
httpOnly、secure、sameSite、expires等字段。 - 注入 session cookie 时不传
expires <= 0,避免 CDP 将整批 cookie 判为非法。
9.2 localStorage
- 注入:按 origin 打开或复用页面上下文后执行
localStorage.setItem。 - 导出:复用当前页面 target;必要时新开 origin target,并等待
location.origin匹配后读取。 - 导出范围只包含本次运行已访问或已注入的 origin。
- 若 origin 页面无法打开或脚本执行失败,不生成 tombstone。
9.3 浏览器实现边界
- 内置 Playwright MCP 是当前推荐且稳定的浏览器登录态链路。
agent_browser通过 Bash 命令识别接入 Auth State hook,但受命令生命周期影响较大,例如同一条 Bash 中执行agent-browser close可能导致导出时页面已关闭。因此登录态复用场景暂不推荐依赖该链路。- 手动启动独立浏览器、独立 profile、独立 agent-browser session/config/state 文件都不属于统一 Auth State 范围。
10. 改造点(文件级)
10.1 Backend
新增:
backend/app/models/user_auth_state.pybackend/app/repositories/user_auth_state_repository.pybackend/app/services/auth_state_service.pybackend/app/schemas/auth_state.pybackend/app/api/v1/internal/auth_state.py- Alembic migration
调整:
backend/app/api/v1/remote_browser.py- 删除浏览器数据时同步清空 Auth State。
- 启动/停止远程浏览器时保持 Auth State 同步语义清晰。
backend/app/core/settings.py- 增加 Auth State 加密相关配置。
.env.example- 增加用户需要配置的加密配置。
docs/zh/configuration.mddocs/en/configuration.md- 如影响 Docker 部署,再同步:
docs/zh/docker-compose.mddocs/en/docker-compose.md
10.2 Executor Manager
新增:
executor_manager/app/services/auth_state_stager.py- 拉取 Backend 快照并写入
/workspace/.poco/auth-state/base.json。 executor_manager/app/services/auth_state_sync_service.py- 任务结束后读取
final.json并提交 Backend。 executor_manager/app/services/browser_auth_state_sync_service.py- 远程浏览器 CDP 导出/注入。
- 维护远程浏览器可信 baseline。
调整:
executor_manager/app/services/backend_client.py- 新增 snapshot/commit/clear 调用。
executor_manager/app/services/run_pull_service.py- 任务启动前调用
AuthStateStager。 executor_manager/app/scheduler/task_dispatcher.py- legacy dispatch 路径同样调用
AuthStateStager。 executor_manager/app/services/callback_service.py- terminal callback 后提交
final.json。 executor_manager/app/services/container_pool.py- 移除任务启动时的 base profile copy。
- 保留临时会话 profile 目录创建。
- 保护 Chrome/agent-browser profile/session/config/state 相关环境变量,避免用户配置绕过统一 Auth State。
executor_manager/app/services/browser_sandbox_manager.py- 远程浏览器启动后注入 Auth State。
- 远程浏览器停止前导出并提交 Auth State。
- 删除数据时清空 Backend Auth State。
executor_manager/app/services/browser_profile_manager.py- 已移除
ensure_session_profile_seeded任务启动调用。 executor_manager/app/schemas/task.py- 已移除
browser_profile_copy_mode。
10.3 Executor
新增:
executor/app/services/auth_state_bridge.py- CDP 注入与导出。
- 浏览器实例指纹检测。
base.json、working.json、final.json读写。executor/app/hooks/auth_state.py- 在 setup 注入状态。
- 在 browser tool 调用前后做自愈与导出。
- 识别 Playwright MCP 工具事件与
agent-browserBash 命令。 - 在 teardown 写入 final state。
调整:
executor/app/api/v1/task.pybrowser_enabled=true且浏览器实现支持 Auth State 时注册 AuthState hook。executor/app/core/engine.py- Playwright MCP 通过 CDP 连接任务容器内 Chrome。
agent_browser模式注入内置 agent-browser skill,并避免重复注入 Playwright MCP。executor/app/schemas/request.py- 已移除
browser_profile_copy_mode相关输入。
11. 实施步骤
- Backend:模型、迁移、加密存储、内部 API 与三方合并逻辑。
- Executor:AuthStateBridge、setup 注入、浏览器工具调用边界导出、teardown 写 final。
- Executor Manager:AuthStateStager、远程浏览器同步、任务启动快照、任务结束提交。
- 移除 profile copy:删除任务启动时的
ensure_session_profile_seeded调用。 - 配置与文档同步:更新
.env.example与中英文配置文档。 - 联调验证:远程浏览器登录、任务复用、任务登录、远程浏览器复用、并发提交。