playwright-cli 浏览器存储状态管理实战指南:Cookies、localStorage、sessionStorage 与认证状态复用
【免费下载链接】sanitySanity Studio – Rapidly configure content workspaces powered by structured content项目地址: https://gitcode.com/GitHub_Trending/sa/sanity
导读
本文围绕 Sanity 仓库中 .agents/skills/playwright-cli 技能所封装的playwright-cli命令行工具,系统讲解其浏览器存储状态(Storage State)管理能力——涵盖 cookies、localStorage、sessionStorage、IndexedDB 的读写删清,以及"保存 → 恢复"完整浏览器状态的认证复用工作流。读完本文,你将掌握如何用state-save/state-load在多次自动化会话间复用登录态、用cookie-*/localstorage-*/sessionstorage-*系列命令细粒度操纵存储数据,并理解存储状态 JSON 文件格式及其背后的安全边界。文章末尾还结合本仓库 e2e 测试体系(如 e2e/playwright.config.ts 中的storageState注入实践),展示该能力的真实工程用法。
Storage State:一键保存与恢复完整浏览器状态
playwright-cli的存储状态(Storage State)能力可以把浏览器当前的全部存储数据——包括 cookies、localStorage、sessionStorage——序列化到磁盘文件,之后在任意新会话中原样还原,是跨会话复用登录态、预置测试数据的核心手段。
保存存储状态
使用state-save命令将当前浏览器上下文中的存储状态落盘:
# 保存到自动生成的文件名(storage-state-{timestamp}.json) playwright-cli state-save # 保存到指定文件名 playwright-cli state-save my-auth-state.json不传文件名时,工具会自动生成带时间戳的 JSON 文件(形如storage-state-2026-09-16T09-00-00-000Z.json),适合临时快照;显式命名则适合作为工作流产物,便于后续state-load精确引用。
恢复存储状态
# 从文件加载存储状态 playwright-cli state-load my-auth-state.json # 重新打开页面以应用 cookies(cookie 需要一次页面加载才会真正生效) playwright-cli open https://example.com注意:
state-load把状态写入当前浏览器上下文后,需要重新导航页面才能看到 cookies 生效(例如已登录站点会直接呈现登录后的界面)。
存储状态文件格式
state-save产出的 JSON 文件结构与 Playwright 官方的storageState完全一致,包含cookies与origins两个顶层字段:
{ "cookies": [ { "name": "session_id", "value": "abc123", "domain": "example.com", "path": "/", "expires": 1735689600, "httpOnly": true, "secure": true, "sameSite": "Lax" } ], "origins": [ { "origin": "https://example.com", "localStorage": [ {"name": "theme", "value": "dark"}, {"name": "user_id", "value": "12345"} ] } ] }字段语义说明:
cookies[]:Cookie 列表,name/value为键值对,domain与path决定其作用域,expires为 Unix 时间戳(秒),httpOnly/secure/sameSite对应浏览器安全属性;origins[]:按源(origin,即协议+域名+端口)分组的 Web Storage 数据,目前主要承载该源下的localStorage键值列表。
由于该格式与 Playwright 官方配置互通,你甚至可以手动编写这样一个 JSON 文件,再通过state-load注入任意浏览上下文——这也正是 e2e/playwright.config.ts 中直接以storageState配置项向测试注入认证 localStorage 的原理(详见文末"仓库实战"一节)。
Cookies 管理
Cookies 是 Web 会话认证的载体,playwright-cli提供了从列出、查询到设置、删除的完整命令面。
列出与过滤
# 列出当前上下文中的所有 cookies playwright-cli cookie-list # 按域名过滤 playwright-cli cookie-list --domain=example.com # 按路径过滤 playwright-cli cookie-list --path=/api--domain与--path可组合使用,例如只查看example.com下/api路径的会话类 Cookie。
查询单个 Cookie
playwright-cli cookie-get session_id按名称精确读取某个 Cookie 的完整属性(value、domain、expires、httpOnly、secure、sameSite 等)。
设置 Cookie
# 基础用法:名称 + 值 playwright-cli cookie-set session abc123 # 带选项的完整用法 playwright-cli cookie-set session abc123 --domain=example.com --path=/ --httpOnly --secure --sameSite=Lax # 带过期时间(Unix 时间戳,秒) playwright-cli cookie-set remember_me token123 --expires=1735689600cookie-set支持的选项与 JSON 文件格式中的字段一一对应:--domain指定生效域名,--path指定路径作用域,--httpOnly/--secure为布尔开关(出现即开启),--sameSite取值通常为Lax、Strict或None,--expires使用 Unix 时间戳控制持久化时长。
删除与清空
# 删除指定 Cookie playwright-cli cookie-delete session_id # 清空当前上下文的所有 cookies playwright-cli cookie-clear进阶:批量设置或自定义复杂 Cookie
当需要一次性添加多个 Cookie,或需要构造cookie-set命令行参数难以表达的属性组合时,使用run-code直接调用 Playwright 上下文 API(playwright-cli run-code的完整能力参见 .agents/skills/playwright-cli/references/running-code.md):
playwright-cli run-code "async page => { await page.context().addCookies([ { name: 'session_id', value: 'sess_abc123', domain: 'example.com', path: '/', httpOnly: true }, { name: 'preferences', value: JSON.stringify({ theme: 'dark' }), domain: 'example.com', path: '/' } ]); }"page.context()返回当前浏览器上下文(BrowserContext),addCookies()一次可注入任意数量的 Cookie,适合模拟完整登录态或测试多 Cookie 场景。
Local Storage 管理
localStorage 属于持久化的源级存储,常用于存放主题偏好、用户 ID、token 缓存等跨页面、跨会话数据。
# 列出当前页面源下的所有 localStorage 条目 playwright-cli localstorage-list # 读取单个键的值 playwright-cli localstorage-get token # 设置普通字符串值 playwright-cli localstorage-set theme dark # 设置 JSON 字符串值(自动序列化) playwright-cli localstorage-set user_settings '{"theme":"dark","language":"en"}' # 删除单个键 playwright-cli localstorage-delete token # 清空当前源的全部 localStorage playwright-cli localstorage-clear注意localstorage-set的第二个参数是字符串;写入对象时需自行传入 JSON 序列化后的字符串(如上面的user_settings示例),读取时再反序列化使用。
进阶:批量写入多个条目
一次设置多个值时,同样通过run-code在页面上下文中执行localStorage.setItem:
playwright-cli run-code "async page => { await page.evaluate(() => { localStorage.setItem('token', 'jwt_abc123'); localStorage.setItem('user_id', '12345'); localStorage.setItem('expires_at', Date.now() + 3600000); }); }"page.evaluate在页面 JS 环境中执行,因此可直接访问浏览器的localStorage全局对象,适合构造"已登录 + 已配置"的完整初始状态。
Session Storage 管理
sessionStorage 的生命周期限定在单个标签页会话内(标签页关闭即清除),适合存放多步表单草稿、分步向导的当前进度等一次性数据。
# 列出所有 sessionStorage 条目 playwright-cli sessionstorage-list # 读取单个值 playwright-cli sessionstorage-get form_data # 设置值 playwright-cli sessionstorage-set step 3 # 删除单个键 playwright-cli sessionstorage-delete step # 清空 sessionStorage playwright-cli sessionstorage-clear与 localStorage 命令一一对应,用法完全对称,区别仅在于数据的作用域与存活周期。值得一提的是,state-save保存的存储状态文件不包含 sessionStorage(它属于页面会话而非上下文状态),因此跨会话恢复依赖的是 cookies 与 localStorage。
IndexedDB:数据库级操作
IndexedDB 是浏览器内置的 NoSQL 数据库,存储容量远大于 Web Storage,常被大型 Web 应用(离线优先、缓存型应用)使用。playwright-cli没有为它提供专门的子命令,统一通过run-code+page.evaluate在页面环境中操作。
列出所有数据库
playwright-cli run-code "async page => { return await page.evaluate(async () => { const databases = await indexedDB.databases(); return databases; }); }"删除指定数据库
playwright-cli run-code "async page => { await page.evaluate(() => { indexedDB.deleteDatabase('myDatabase'); }); }"indexedDB.databases()返回当前源下的数据库元信息数组;indexedDB.deleteDatabase('myDatabase')按名称删除数据库(存在未关闭连接时会触发blocked事件,脚本中按需处理)。这两段代码可作为操作 IndexedDB 的基础模板,更复杂的对象仓库(object store)读写同样可以在page.evaluate中完成。
常见模式:认证状态复用与保存/恢复往返
模式一:登录一次,处处复用(Authentication State Reuse)
这是存储状态管理最典型、价值最高的场景——先手动完成一次登录,把认证态固化到文件,之后的自动化任务直接恢复状态跳过登录步骤:
# Step 1:打开登录页并完成登录 playwright-cli open https://app.example.com/login playwright-cli snapshot playwright-cli fill e1 "user@example.com" playwright-cli fill e2 "password123" playwright-cli click e3 # 保存认证状态 playwright-cli state-save auth.json # Step 2:之后任意时刻恢复状态,直接访问受保护页面 playwright-cli state-load auth.json playwright-cli open https://app.example.com/dashboard # 已经是登录状态,无需再次登录!snapshot用于获取页面元素的可访问性引用(如e1、e2、e3),随后fill/click依据这些引用完成交互——这是 SKILL.md 中规定的标准交互流程。
模式二:保存与恢复往返(Save and Restore Roundtrip)
不依赖完整登录流程,也可以直接构造状态再固化:
# 设置认证状态 playwright-cli open https://example.com playwright-cli eval "() => { document.cookie = 'session=abc123'; localStorage.setItem('user', 'john'); }" # 保存状态到文件 playwright-cli state-save my-session.json # …… 稍后,在新的会话中 …… # 恢复状态 playwright-cli state-load my-session.json playwright-cli open https://example.com # Cookies 和 localStorage 都已恢复!eval允许直接在页面上下文中执行 JS 表达式(如设置document.cookie与localStorage),与state-save配合可快速生成可复用的状态快照。结合 session-management.md 中的-s命名会话机制,你还可以为不同账号分别保存auth-admin.json、auth-editor.json,在互相隔离的浏览器会话中并行执行不同角色场景。
安全注意事项
存储状态文件本质上是凭证的序列化副本,泄露即等于交出登录态,务必遵守以下安全约定:
- 绝不提交包含认证令牌的存储状态文件到版本控制;
- 将
*.auth-state.json加入.gitignore(本仓库根目录的 .gitignore 相关约定 之外,任何涉及认证状态的文件都应显式忽略); - 自动化任务完成后及时删除状态文件,避免长期滞留磁盘;
- 敏感数据(如真实 token)优先通过环境变量注入,而非写死在状态文件或命令中;
- 默认情况下,会话以内存模式运行(不落盘 profile,详见 session-management.md 中的持久化 profile 说明),这对敏感操作更安全;仅在确实需要跨会话持久化时才显式使用
state-save或--persistent。
仓库实战:storageState 在 Sanity E2E 中的工程应用
本仓库的端到端测试体系恰好印证了"存储状态"思想的工程化落地——虽然 Sanity e2e 直接使用 Playwright 测试框架而非playwright-cli命令,但两者共享完全相同的 storageState 数据格式。
在 e2e/playwright.config.ts 中,Playwright 的use.storageState配置直接内联了一段存储状态 JSON,向每个测试上下文注入 Sanity Studio 的认证 token:
storageState: { cookies: [], origins: [ { origin: BASE_URL, localStorage: [ { name: `__studio_auth_token_${PROJECT_ID}`, value: JSON.stringify({ token: TOKEN, time: new Date().toISOString(), }), }, ], }, ], },其中TOKEN来自SANITY_E2E_SESSION_TOKEN环境变量(见 e2e/helpers/envVars.ts),通过localStorage键__studio_auth_token_{projectId}预置登录态——这正是 Sanity Studio 前端读取会话 token 的存储位置。可以看到,"用 JSON 描述 cookies + localStorage,再整体注入浏览器上下文"的模式,与playwright-cli state-load背后是完全一致的机制,只不过 Playwright 测试配置里是声明式的,而 CLI 中是从文件加载。
与之配套,认证类测试单独使用 e2e/playwright.auth.config.ts(针对 dev/auth-test-studio 的 cookie/token 双工作区),并在 e2e/tests/auth/helpers.ts 中通过路由 mock 模拟登录 API 响应。这展示了存储状态管理的两种策略:
- 真实登录 + 保存/恢复:适合复用真实认证态(
playwright-cli场景); - 直接注入构造的状态:适合测试环境,无需真实凭证即可预置任意登录态(Sanity e2e 场景)。
理解了 storageState 文件格式与注入机制后,你可以自由地在两条路线之间切换——既可以用playwright-cli state-save从手工登录会话导出状态文件,也可以手工编写 JSON 后用state-load注入,甚至像本仓库一样在测试配置中声明式内联。
小结
playwright-cli的存储管理命令构成了一个"查看 → 修改 → 固化 → 复用"的完整闭环:cookie-*、localstorage-*、sessionstorage-*负责细粒度读写,state-save/state-load负责整体快照的保存与恢复,run-code补足 IndexedDB 与批量操作的进阶场景,而 session-management.md 中的命名会话与持久化 profile 则定义了这些存储数据的隔离与存活边界。配合文末的安全清单,这套能力足以支撑认证复用、多角色并行测试、状态预置等绝大多数浏览器自动化需求。
【免费下载链接】sanitySanity Studio – Rapidly configure content workspaces powered by structured content项目地址: https://gitcode.com/GitHub_Trending/sa/sanity
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考