如何在 shell 中动态获取 chrome 浏览器的 cookie 信息

V2EX

0. 背景

在工作的时候,经常要接触一些办公系统,在网页上通过机械化的操作,来完成一个简单的功能,比如某台主机权限的申请,通过一套操作一下,大概 7、8 个步骤,花费 30 秒的时间,虽然不长,但是要脱离终端,到浏览器去操作,打断了心流,就感觉很烦人了。我们在网页的操作,其实就是往这个网站的后台发起一个 API 请求,这个动作,我们在终端里面,通过 curl 命令也能完成,比如我们打开百度的首页,通过 chrome 的控制台 -> Network -> 找到对应的请示,右键,Copy -> Copy as cURL,我们就能得到如下的一条命令:

curl 'https://www.baidu.com/' -H 'Connection: keep-alive' -H 'Cache-Control: max-age=0' -H 'Upgrade-Insecure-Requests: 1' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36' -H 'Sec-Fetch-Mode: navigate' -H 'Sec-Fetch-User: ?1' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3' -H 'Sec-Fetch-Site: none' -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Language: zh-CN,zh;q=0.9,en;q=0.8' -H 'Cookie: BIDUPSID=A10629EBE8B29EBEE170B7E4E405; PSTM=1520729161; BDUSS=pMV2FGNlNaUUdB134asdfCOVU5cHFCR0p2SzBtY0Q2OWlNZlhORHdhN1ZjQVFBQUFBJCQAAAAAABBBBBGHAAaG9tZXdheQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPDejVzw3o1cck; ' --compressed

在终端执行这条命令,和你浏览器发起的这个请求,其实是等同的,但是这里面,有一个最重要的参数,就是你的 Cookie 信息,这个信息可以代表你当前在这个网站上的登录用户,如果我们要写一些自动化的网站操作脚本,或者写爬虫什么的,第一步就是怎么拿到 cookie 信息。

1. 获取 chrome 浏览器里的 cookie

cookie 信息,肯定是存储在 chrome 中,具体的存储位置未知,并且对于这么隐私的数据,应该也是会进行加密存储的,因此,我并没有去尝试通过读取 cookie 文件的方式。

想起之前用过一个模拟发请求的 chrome 插件,postman,通过安装Postman Interceptor拦截器,可以让我们在postman里模拟发请求的时候,自动带上网站的 cookie 信息,但是查阅了postman的相关资料,也没有开放接口让我们在其它地方可以拿到 cookie 信息。

1.1 通过 chrome 插件获取 cookie 数据

既然在浏览器插件里能拿到 cookie,那么我们自己实现一个不就行了吗,拿到数据之后,再想办法把数据传出来就可以了。参考 chrome api 文档,我们可以通过添加一个 cookies 的监听器,来拿到变化的 cookie,以及拿到某个 domain 域下的所有 cookie,但是 chrome 也是运行在浏览器环境之上,无法直接往本地存储写数据,只能通过对外发起 ajax 请求来把数据传出去了。核心代码如下:

function refreshDomain(domain) {
	chrome.cookies.getAll({domain: domain}, function (cookies) {
		
		let all_cookies = cookies.filter(item => item.domain === domain)
			.map(item => item.name + "=" + item.value).join("; ");

		console.log("Report Cookie:domain=" + domain + ",cookies=" + all_cookies);
		$.ajax({
			 
			url: "http://localhost:8888",
			method: "POST",
			data: {
				domain: domain,
				cookies: all_cookies
			},
			dataType: "json",
			success: function(data) { console.log("Report success:" + data) },
			failure: function (data) {
				console.log("Report failure:" + data)
			}
		})
	});
}

chrome.cookies.onChanged.addListener(function (event) {
	const cookie = event.cookie;
	refreshDomain(cookie.domain);
});

1.2 接收数据并存储

这里还需要实现一个 http 服务来接收插件发出来的 cookie 数据,这里我用 spring boot 初始化出来一个 spring mvc 的工程,再添加两个 api,一个用于接收 cookie 并存储,一个用于对外再接供获取 cookie 信息的接口。代码如下:

@SpringBootApplication
@EnableWebMvc
@Controller
public class CookieManager {
	private static Map<String, String> domainCookies = new HashMap<>(1024);

	@RequestMapping(value = "/", method = RequestMethod.GET)
	@ResponseBody
	public String getCookie(@RequestParam("domain") String domain) {
		return domainCookies.entrySet().stream()
			.filter(e -> domain.endsWith(e.getKey()))
			.map(Entry::getValue)
			.collect(Collectors.joining("; "));
	}

	@RequestMapping(value = "/", method = RequestMethod.POST)
	@ResponseBody
	public String setCookie(@RequestParam("domain") String domain,
							@RequestParam("cookies") String cookies) throws IOException {

		domainCookies.put(domain, cookies);

		return domain;
	}

	public static void main(String[] args) {
		SpringApplication.run(CookieManager.class, args);
	}
}

这里在获取 cookie 的时候做了一个处理,自动把父域的 cookie 带上。比如获取 domain=www.baidu.com 的 cookie,会把 domain=.baidu.com 的数据也返回

1.3 在 shell 中的用法

COOKIE=$(wget localhost:8888/?domain=www.baidu.com -q -O -)
echo $COOKIE

curl 'https://www.baidu.com/' -H "Cookie:  $COOKIE"

注意这里"Cookie: $COOKIE"必须是双引号,不能用单引号。

特别注意

cookie 信息是一个非常隐私和重要的数据,虽然通过这个方法,能够将浏览器里面这个数据导出来,但对于这个数据,是需要特别小心保存的,cookie 信息如果被别人拿到,相当于别人可以用你的身份做任何事情,这是非常危险的。因此本文只是作为一个例子,没有做任何加密,但在实际应用中,最好都做加密传输。

参考文档

本文由 黑白世界4648 第一时间收藏到GET,原文来自 → www.v2ex.com

「GetParty」

关注微信号,推送好文章

微信中长按图片即可关注

更多精选文章

评论
微博一键登入