Puppeteer setCookie设置踩坑
Author:zhoulujun Date:
看官网文档:https://pptr.cn/guides/cookies
localhost的坑
puppeteer设置cookie,在 page.setcookie方法失效,需要在browser设置,官方文档如下:
https://pptr.dev/api/puppeteer.browser.setcookie
await browser.setCookie(...cookiesArr)
但是我发现,Browser.setCookie() 无法跨域设置cookies,也没法设置 domain 为localhost
而且在本地开发,测试域名基本为localhost,才能调试
这个时候,只有把测试域名换为127.0.0.1
或者把设置puppeteer的CSP策略
cookies属性的坑
cookies属性有很多,但是官方并没有说明有哪些是必填属性。
比如domain是必填项,但是官方表格是可选项!
每个cookie,必填name、value、domain
Property | Modifiers | Type | Description | Default |
---|---|---|---|---|
domain |
| string | Cookie domain. | |
expires |
| number | Cookie expiration date, session cookie if not set | |
httpOnly |
| boolean | True if cookie is http-only. | |
name | string | Cookie name. | ||
partitionKey |
| CookiePartitionKey | string | Cookie partition key. In Chrome, it matches the top-level site the partitioned cookie is available in. In Firefox, it matches the source origin (https://w3c.github.io/webdriver-bidi/\#type-storage-PartitionKey). | |
path |
| string | Cookie path. | |
priority |
| Cookie Priority. Supported only in Chrome. | ||
sameParty |
| boolean | True if cookie is SameParty. Supported only in Chrome. | |
sameSite |
| Cookie SameSite type. | ||
secure |
| boolean | True if cookie is secure. | |
sourceScheme |
| Cookie source scheme type. Supported only in Chrome. | ||
url |
| string | The request-URI to associate with the setting of the cookie. This value can affect the default domain, path, and source scheme values of the created cookie. | |
value | string | Cookie value. |
domain标识指定了哪些主机可以访问该Cookie的域名。如果设置为“.google.com”,则所有以“google.com”结尾的域名都可以访问该Cookie。注意第一个字符必须为“.” 如果是ip 端口访问
默认是不同端口可共享,注:端口和域无关,也就是说Cookie的域是不包括端口的,这里不要带上端口,都在浏览器无法写入cookie
Cookie的生命周期
情况下,Cookie的生命周期是Session级别(会话级别)。若想用Cookie进行状态保存、资源共享,服务端一般都会给其设置一个过期时间maxAge,短则1小时、1天,长则1星期、1个月甚至永久,这就是Cookie的生命(周期)。Cookie的存储形式,根据其生命周期的不同而不同。这由maxAge属性决定,共有这三种情况:
maxAge > 0:cookie不仅内存里有,还会持久化到硬盘,也叫持久Cookie。这样的话即使你关机重启(甚至过几天再访问),这个cookie依旧存在,请求时依旧会携带
maxAge < 0:一般值为-1,也就临时Cookie。该Cookie只在内存中有(如session级别),一旦管理浏览器此Cookie将不复存在。值得注意的是:若使用无痕模式访问也是不会携带此Cookie的哟
maxAge = 0:内存中没有,硬盘中也没有了,也就立即删除Cookie。此种case存在的唯一目的:服务浏览器可能的已存在的cookie,让其立马失效(消失)
请注意maxAge<0(负数)和maxAge=0的区别。前者会存在于内存,只有关闭浏览器or重启才失效;后者是立即删除
跨域Cookie共享的三要素
首先确保服务端能正确的在响应中有Set-Cookie响应头,这由Access-Control-Allow-Credentials: true来保证。因此服务端只需要做多加这一步即可:
resp.setHeader("Access-Control-Allow-Credentials", "true");
Access-Control-Allow-Credentials该头是可选的,是个bool值,它若为true就有两个作用:
在跨域请求的响应中允许Set-Cookie响应头
浏览器收到响应后,浏览器根据此头判断是否让自己的withCredentials属性生效第二个要素:XMLHttpRequest对象的withCredentials属性。当异步对象设置了withCredentials=true时,浏览器会保留下响应的Cookie等信息,并且下次发送请求时将其携带。因此要指示浏览器存储Cookie并且每次跨域请求都携带,仅需加上此参数即可:
以上两个要素完成后,影响“结果”的还有最后一个要素。
服务端的Access-Control-Allow-Origin这个响应头的值不能是通配符*,而只能是具体的值。否则出现报错:
换句话讲:浏览器端跨域请求对象一旦开启withCredentials=true属性,服务端跨域Origin将不能再用*通配符,否则CORS error!
三要素都满足(Access-Control-Allow-Credentials:true; Access-Control-Allow-Origin:http://localhost:63342; withCredentials=true)
劫持xhr,手动注入cookie
这个是笨办法,但是特别好用
await page.setRequestInterception(true)
page.on('request', (req) => {
if (req.resourceType() === 'xhr') {
const headers = req.headers()
const reqCookies = headers.cookie
cookiesArr.forEach((name) => {
if (cookies[name] && !reqCookies?.includes(`${name}=`)) {
if (!reqCookies.length || reqCookies.endsWith(';')) {
headers.cookie += ` ${name}=${cookies[name]};`
} else {
headers.cookie += `; ${name}=${cookies[name]}`
}
}
})
req.continue({ headers })
} else {
req.continue()
}
})
转载本站文章《Puppeteer setCookie设置踩坑》,
请注明出处:https://www.zhoulujun.cn/html/webfront/browser/Puppeteer/9432.html