-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
1 addition
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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} |