--- name: 存储与认证 description: 管理 Cookie、localStorage、sessionStorage、浏览器存储状态,保存与恢复认证,或测试依赖存储的功能 metadata: type: reference --- # 存储与认证 > **使用场景**:管理 Cookie、localStorage、sessionStorage、浏览器存储状态,保存与恢复认证,或测试依赖存储的功能。 > **前置条件**:[core-commands.md](core-commands.md)——了解基本 CLI 用法 ## 快速参考 ```bash # 将所有浏览器状态(Cookie + localStorage)保存到文件 playwright-cli state-save auth.json # 在新会话中恢复状态 playwright-cli state-load auth.json # 快速 Cookie 操作 playwright-cli cookie-list playwright-cli cookie-set session_id abc123 --domain=example.com --httpOnly --secure playwright-cli cookie-delete session_id playwright-cli cookie-clear # localStorage playwright-cli localstorage-set theme dark playwright-cli localstorage-get theme playwright-cli localstorage-clear # sessionStorage playwright-cli sessionstorage-set step 3 playwright-cli sessionstorage-get step playwright-cli sessionstorage-clear ``` ## 存储状态(保存与恢复) 最强大的功能——将整个浏览器状态(所有来源的 Cookie + localStorage)保存到一个 JSON 文件中,之后恢复该状态以跳过登录流程。 ### 保存存储状态 ```bash # 保存到自动生成的文件名(storage-state-{timestamp}.json) playwright-cli state-save # 保存到指定文件 playwright-cli state-save auth.json playwright-cli state-save ./states/admin-session.json ``` ### 恢复存储状态 ```bash # 从文件加载状态 playwright-cli state-load auth.json # 加载后导航——Cookie 和 localStorage 已设置好 playwright-cli goto https://app.example.com/dashboard # 已通过认证! ``` ### 存储状态文件格式 保存的 JSON 同时包含 Cookie 和 localStorage: ```json { "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" }, { "name": "auth_token", "value": "jwt.token.here" } ] } ] } ``` ## 认证模式 最常用的工作流程——登录一次,保存状态,跨会话复用。 ### 步骤 1:登录并保存 ```bash playwright-cli open https://app.example.com/login playwright-cli snapshot playwright-cli fill e1 "admin@example.com" playwright-cli fill e2 "secure-password" playwright-cli click e3 # 等待重定向以确认登录成功 playwright-cli run-code "async page => { await page.waitForURL('**/dashboard'); return 'Login successful: ' + page.url(); }" # 保存已认证的状态 playwright-cli state-save auth.json playwright-cli close ``` ### 步骤 2:复用认证状态 ```bash # 新会话——完全跳过登录 playwright-cli open https://app.example.com playwright-cli state-load auth.json playwright-cli goto https://app.example.com/dashboard # 已以管理员身份登录! playwright-cli snapshot # 查看仪表盘 ``` ### 多角色认证 ```bash # 为每个角色保存状态 playwright-cli open https://app.example.com/login playwright-cli fill e1 "admin@example.com" playwright-cli fill e2 "admin-pass" playwright-cli click e3 playwright-cli state-save admin-auth.json playwright-cli close playwright-cli open https://app.example.com/login playwright-cli fill e1 "user@example.com" playwright-cli fill e2 "user-pass" playwright-cli click e3 playwright-cli state-save user-auth.json playwright-cli close # 现在使用它们 playwright-cli -s=admin open https://app.example.com playwright-cli -s=admin state-load admin-auth.json playwright-cli -s=admin goto https://app.example.com/admin playwright-cli -s=user open https://app.example.com playwright-cli -s=user state-load user-auth.json playwright-cli -s=user goto https://app.example.com/profile ``` ### OAuth / SSO 认证 针对涉及重定向和弹出窗口的 OAuth 流程: ```bash playwright-cli run-code "async page => { await page.goto('https://app.example.com/login'); // 点击"使用 Google 登录" const [popup] = await Promise.all([ page.waitForEvent('popup'), page.click('button:text(\"Login with Google\")') ]); // 在弹出窗口中填写凭据 await popup.fill('input[type=email]', 'user@gmail.com'); await popup.click('#identifierNext'); await popup.fill('input[type=password]', 'password'); await popup.click('#passwordNext'); // 等待弹出窗口关闭且主页面完成重定向 await popup.waitForEvent('close'); await page.waitForURL('**/dashboard'); // 保存已认证状态 await page.context().storageState({ path: 'oauth-auth.json' }); return 'OAuth login complete'; }" ``` ## Cookies ### 列出所有 Cookie ```bash playwright-cli cookie-list ``` ### 按域名筛选 ```bash playwright-cli cookie-list --domain=example.com ``` ### 按路径筛选 ```bash playwright-cli cookie-list --path=/api ``` ### 获取指定 Cookie ```bash playwright-cli cookie-get session_id playwright-cli cookie-get __cf_bm ``` ### 设置 Cookie ```bash # 基础 Cookie playwright-cli cookie-set session abc123 # 带完整选项的 Cookie playwright-cli cookie-set session abc123 \ --domain=example.com \ --path=/ \ --httpOnly \ --secure \ --sameSite=Lax # 带过期时间的 Cookie(Unix 时间戳) playwright-cli cookie-set remember_me token123 --expires=1735689600 ``` ### 删除 Cookie ```bash playwright-cli cookie-delete session_id playwright-cli cookie-delete __cf_bm ``` ### 清除所有 Cookie ```bash playwright-cli cookie-clear ``` ### 高级:一次设置多个 Cookie ```bash playwright-cli run-code "async page => { await page.context().addCookies([ { name: 'session_id', value: 'sess_abc123', domain: 'example.com', path: '/', httpOnly: true, secure: true, sameSite: 'Strict' }, { name: 'preferences', value: JSON.stringify({ theme: 'dark', lang: 'en' }), domain: 'example.com', path: '/' }, { name: 'tracking_opt_out', value: 'true', domain: '.example.com', path: '/' } ]); }" ``` ### 高级:编程方式读取所有 Cookie ```bash playwright-cli run-code "async page => { const cookies = await page.context().cookies(); return cookies.map(c => ({ name: c.name, value: c.value.substring(0, 20) + '...', domain: c.domain, httpOnly: c.httpOnly, secure: c.secure, expires: new Date(c.expires * 1000).toISOString() })); }" ``` ## Local Storage ### 列出所有项目 ```bash playwright-cli localstorage-list ``` ### 获取值 ```bash playwright-cli localstorage-get theme playwright-cli localstorage-get auth_token ``` ### 设置值 ```bash playwright-cli localstorage-set theme dark playwright-cli localstorage-set language en-US # 设置 JSON 值(对 JSON 加引号) playwright-cli localstorage-set user_settings '{"theme":"dark","fontSize":14,"sidebar":true}' ``` ### 删除项目 ```bash playwright-cli localstorage-delete auth_token ``` ### 清除所有 ```bash playwright-cli localstorage-clear ``` ### 高级:批量操作 ```bash playwright-cli run-code "async page => { await page.evaluate(() => { localStorage.setItem('token', 'jwt_abc123'); localStorage.setItem('user_id', '12345'); localStorage.setItem('user_name', 'Jane Doe'); localStorage.setItem('preferences', JSON.stringify({ theme: 'dark', notifications: true, language: 'en' })); localStorage.setItem('onboarding_complete', 'true'); }); }" ``` ### 高级:读取所有 localStorage ```bash playwright-cli run-code "async page => { return await page.evaluate(() => { const items = {}; for (let i = 0; i < localStorage.length; i++) { const key = localStorage.key(i); items[key] = localStorage.getItem(key); } return items; }); }" ``` ## Session Storage Session storage 按标签页隔离,关闭标签页时自动清除。 ### 列出所有项目 ```bash playwright-cli sessionstorage-list ``` ### 获取 / 设置 / 删除 ```bash playwright-cli sessionstorage-get form_step playwright-cli sessionstorage-set form_step 3 playwright-cli sessionstorage-set form_data '{"name":"Jane","email":"jane@example.com"}' playwright-cli sessionstorage-delete form_step playwright-cli sessionstorage-clear ``` ## IndexedDB IndexedDB 需要通过 `run-code` 进行访问: ### 列出数据库 ```bash playwright-cli run-code "async page => { return await page.evaluate(async () => { const databases = await indexedDB.databases(); return databases.map(db => ({ name: db.name, version: db.version })); }); }" ``` ### 删除数据库 ```bash playwright-cli run-code "async page => { await page.evaluate(dbName => { indexedDB.deleteDatabase(dbName); }, 'myDatabase'); return 'Database deleted'; }" ``` ### 从对象存储中读取数据 ```bash playwright-cli run-code "async page => { return await page.evaluate(() => { return new Promise((resolve, reject) => { const request = indexedDB.open('myDatabase'); request.onsuccess = () => { const db = request.result; const tx = db.transaction('myStore', 'readonly'); const store = tx.objectStore('myStore'); const getAll = store.getAll(); getAll.onsuccess = () => resolve(getAll.result); getAll.onerror = () => reject(getAll.error); }; request.onerror = () => reject(request.error); }); }); }" ``` ## 常见模式 ### Token 刷新测试 ```bash # 设置一个已过期的 Token 以测试刷新逻辑 playwright-cli localstorage-set auth_token "expired-jwt-token" playwright-cli localstorage-set token_expiry "1609459200" # 导航以触发 Token 刷新 playwright-cli goto https://app.example.com/dashboard # 检查 Token 是否已刷新 playwright-cli localstorage-get auth_token ``` ### 功能开关测试 ```bash # 通过 localStorage 启用功能开关 playwright-cli localstorage-set feature_flags '{"newCheckout":true,"darkMode":true,"betaFeatures":false}' # 重新加载以生效 playwright-cli reload playwright-cli snapshot ``` ### 清除所有内容,从头开始 ```bash playwright-cli cookie-clear playwright-cli localstorage-clear playwright-cli sessionstorage-clear playwright-cli reload ``` ### 保存与恢复的完整流程 ```bash # 手动设置状态 playwright-cli open https://example.com playwright-cli cookie-set session abc123 --domain=example.com playwright-cli localstorage-set user john playwright-cli localstorage-set theme dark # 保存所有内容 playwright-cli state-save my-session.json # 之后——在新会话中恢复状态 playwright-cli open https://example.com playwright-cli state-load my-session.json playwright-cli reload # Cookie 和 localStorage 已恢复 ``` ## 安全注意事项 - **切勿提交认证状态文件**——将 `*.auth-state.json` 和 `auth.json` 添加到 `.gitignore` - **使用后删除状态文件**——自动化完成后执行 `rm auth.json` - **使用环境变量保存凭据**——绝不在脚本中硬编码密码 - **内存会话更安全**——默认会话不会持久化到磁盘,降低了暴露风险 - **轮换已保存的状态**——认证 Token 会过期;请定期重新生成状态文件 - **避免在共享机器上保存状态**——存储状态文件包含会话 Token 和个人数据