Skip to content

Commit

Permalink
update get-chrome-cookie
Browse files Browse the repository at this point in the history
  • Loading branch information
qwertyyb committed Oct 24, 2024
1 parent b363693 commit 0806a7d
Showing 1 changed file with 1 addition and 0 deletions.
1 change: 1 addition & 0 deletions data/articles/get-chrome-cookie/index.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"title":"获取 Chrome 浏览器 Cookie","content":"{\"type\":\"doc\",\"content\":[{\"type\":\"heading\",\"attrs\":{\"level\":2,\"align\":\"left\"},\"content\":[{\"type\":\"text\",\"text\":\"Why Not chrome-cookie-secure\"}]},{\"type\":\"paragraph\",\"attrs\":{\"align\":\"left\"},\"content\":[{\"type\":\"text\",\"text\":\"源起于 nodejs 环境下需要自动化的获取浏览器的 Cookie 并在后续请求的 headers 中添加以启用身份认证。\"}]},{\"type\":\"paragraph\",\"attrs\":{\"align\":\"left\"},\"content\":[{\"type\":\"text\",\"text\":\"经过搜索,找到了一个库 \"},{\"type\":\"text\",\"marks\":[{\"type\":\"link\",\"attrs\":{\"href\":\"https://www.npmjs.com/package/chrome-cookies-secure?activeTab=readme\"}}],\"text\":\"chrome-cookie-secure \"},{\"type\":\"text\",\"text\":\"能够获取 Chrome 浏览器的 Cookie。然而使用过程并不顺利,我在用的版本是 MacOS chrome 130,chrome-cookie-secure 的版本是 2.1.1,运行并不能成功获取到 Cookie,中间报了一个错误,似乎是解密失败。\"}]},{\"type\":\"paragraph\",\"attrs\":{\"align\":\"left\"},\"content\":[{\"type\":\"text\",\"text\":\"去查看了一下 \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"chrome-cookie-secure\"},{\"type\":\"text\",\"text\":\" 的源码,大概是读取 Chrome 浏览器的 sqlite 数据库,cookie 是加密存储在 sqlite 数据库中的,所以需要再进行解密才能正常读取到数据。有可能是 Chrome 浏览器更新了加密算法或者是库的解密算法有问题导致了解密失败。\"}]},{\"type\":\"paragraph\",\"attrs\":{\"align\":\"left\"},\"content\":[{\"type\":\"text\",\"text\":\"使用这个库也比较有压力,主要在于它需要读取授权读取存储在 keychain 中的密钥,所以如果要自动化的读取 cookie,就需要给到永久授权,考虑到供应链投毒频发,安全方面的风险实在是太高了。其次也因为这个库读取的 cookie 并不是实时的,按 \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"chrome-cookie-secure\"},{\"type\":\"text\",\"text\":\" 库的官方文档说法,chrome 会每 30 秒同步一次 cookie 到数据库,所以就会有最长 30 秒的延迟。\"}]},{\"type\":\"paragraph\",\"attrs\":{\"align\":\"left\"}},{\"type\":\"heading\",\"attrs\":{\"level\":2,\"align\":\"left\"},\"content\":[{\"type\":\"text\",\"text\":\"解决方案\"}]},{\"type\":\"paragraph\",\"attrs\":{\"align\":\"left\"},\"content\":[{\"type\":\"text\",\"text\":\"考虑到这个库的种种问题,需要另寻方案来解决。\"}]},{\"type\":\"paragraph\",\"attrs\":{\"align\":\"left\"},\"content\":[{\"type\":\"text\",\"text\":\"因为项目本身是使用了 puppeteer 的 connect 来连接现有的 chrome 浏览器的,所以我首先肯定是考虑能不能通过 puppeteer 来获取到 cookie。puppeteer 有一个 \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"Page.cookies()\"},{\"type\":\"text\",\"text\":\" 可以获取页面的 cookie,然而问题在于只能获取当前页面的 cookie,所以需要首先打开目标页,然后再通过这个 API 来获取到 Cookie ,这实在是太慢了,还不如直接打开后续要请求的接口地址,这样也就不需要获取 cookie 了。那为什么我不这么做呢?首先是我链接到当前 Chrome 用的是 headful 模式,如果打开一个新页面,chrome 是会自动聚焦到新页面的,即使后面关闭了页面,用户也是能感知到的,体验非常不好。\"}]},{\"type\":\"paragraph\",\"attrs\":{\"align\":\"left\"},\"content\":[{\"type\":\"text\",\"text\":\"经过搜索,找到了一种方案,即通过 \"},{\"type\":\"text\",\"marks\":[{\"type\":\"link\",\"attrs\":{\"href\":\"https://chromedevtools.github.io/devtools-protocol/tot/Storage/#method-getCookies\"}}],\"text\":\"CDP(Chrome Devtools Protocol)协议\"},{\"type\":\"text\",\"text\":\" 的 \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"Storage.getCookies\"},{\"type\":\"text\",\"text\":\" API 来获取所有的 Cookie,然后过滤出需要的 Cookie。需要说明的是 \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"puppeteer\"},{\"type\":\"text\",\"text\":\" 应该也是通过 CDP 协议来操作的,所以基于 \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"puppeteer\"},{\"type\":\"text\",\"text\":\" 来调用 CDP 中的 API 也是很方便的,最终代码如下:\"}]},{\"type\":\"code_block\",\"attrs\":{\"language\":\"JavaScript\"},\"content\":[{\"type\":\"text\",\"text\":\"export const getCookies = async (domains: string[]) => {\\n // 连接到当前的 Chrome 浏览器\\n const browser = await connectFull()\\n // 创建一个 CDP 会话\\n const client = await browser.target().createCDPSession()\\n // 通过会话调用 Storage.getCookies\\n const result = await client.send('Storage.getCookies')\\n // 获得结果后,销毁调用会话\\n client.connection().dispose()\\n // 过滤出目标域名的 cookie\\n const cookies = result.cookies.filter(c => domains.includes(c.domain))\\n // 拼接成字符串,待 fetch 方法使用\\n return cookies.map(i => `${i.name}=${i.value}`).join('; ')\\n}\"}]},{\"type\":\"paragraph\",\"attrs\":{\"align\":\"left\"}}]}","createdAt":"2024-10-22T08:57:38.539Z","updatedAt":"2024-10-24T08:11:36.831Z","iv":"","encrypted":false}

0 comments on commit 0806a7d

Please sign in to comment.