javascript - Node-Fetch POST 返回与 Firefox POST 不同的结果
问题描述
我能够使用 Firefox 成功登录网站,但无法使用 node-fetch 复制该登录。登录过程分为三个阶段:
- 转到 /login 和网站以 sessionToken 响应(这部分工作正常)
- 在 sessionToken 旁边输入电子邮件和密码,网站以 sessionToken 和 authToken 响应(这是我遇到问题的部分)
- 使用 sessionToken 和 authToken 向 /portal 请求,网站以我尝试访问的 HTML 响应
在 Firefox 开发工具中,我可以看到工作标头和工作请求正文。当我在开发工具中单击“请求”时,我会看到一个“表单数据”标题,其中包含“电子邮件”和“密码”的正确值。当我在开发工具中单击“标题”时,这是成功的 Firefox 请求:
POST /login/action HTTP/2
Host: www.website.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 46
Origin: https://www.website.com
Connection: keep-alive
Referer: https://www.website.com/login
Cookie: _sessiontoken=sessionTokenHere
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
TE: trailers
在 Firefox 上,它会返回带有以下标头的 302(重定向)响应:
HTTP/2 302 Found
date: Sun, 31 Oct 2021 17:25:03 GMT
content-type: text/html; charset=utf-8
cache-control: no-cache
location: https://www.website.com/portal
x-runtime: 9
set-cookie: auth_token=authtokenHere; path=/
set-cookie:
set-cookie: _sessiontoken=sessionTokenHere; path=/; HttpOnly
cf-cache-status: DYNAMIC
[omitted for brevity: expect-ct, report-to, nel, server, cf-ray, alt-svc, X-Firefox-Spdy]
现在,这是我尝试在 node.js 中与 node-fetch 一起使用的 POST 选项:
{
method: 'POST', headers: {
Host: 'www.website.com'
,'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0'
,Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.5',
'Accept-Encoding': 'gzip, deflate, br',
'Content-Length': 46,
Origin: 'https://www.website.com',
Connection: 'keep-alive',
Referer: 'https://www.website.com/login',
Cookie: '_sessiontoken=sessionTokenHere'
'Upgrade-Insecure-Requests': '1',
'Sec-Fetch-Dest': 'document',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'same-origin',
'Sec-Fetch-User': '?1',
TE: 'trailers',
body: URLSearchParams { 'email' => 'myEmail','password' => 'myPassword'}
但是,当使用带有上述选项的 node-fetch 时,它返回 200,而不是 302。以下是该响应的标头(通过 fetch() 函数中的 console.log() 打印):
[Object: null prototype] {
date: [ 'Sun, 31 Oct 2021 18:12:01 GMT' ],
'content-type': [ 'text/html; charset=utf-8' ],
'transfer-encoding': [ 'chunked' ],
connection: [ 'keep-alive' ],
vary: [ 'Accept-Encoding' ],
'x-runtime': [ '5' ],
'cache-control': [ 'private, max-age=0, must-revalidate' ],
'set-cookie': [
'_sessionToken=sessionTokenHere; path=/; HttpOnly'
],
'cf-cache-status': [ 'DYNAMIC' ],
'content-encoding': [ 'br' ],
[omitted for brevity: expect-ct, report-to, nel, server, cf-ray, alt-svc]
}
我很困惑为什么它可以在 Firefox 中工作,但不能在 node-fetch 中工作。几点注意事项:
- 我怀疑我以某种方式错误地包含了电子邮件和密码,但我不知道如何
- 有效的 Firefox 请求在响应头中包含“X-Firefox-Spdy”;非工作节点获取请求没有。
- 根据这篇文章的建议,我的请求中没有包含“Content-Type”
- Firefox 请求似乎使用的是 HTTP/2。这可能是问题的一部分吗?
解决方案
node-fetch自动跟随重定向。它将自动转到下一个重定向的 url(Location
http 标头值)。
如果您想捕捉 301 或 302 呼叫,您可以在选项中设置redirect
属性为,这样您就可以自己管理重定向manual
redirect: "manual"
例如,以下代码将捕获调用(理论上301
它会为您做同样的事情,在此处实现):302
const fetch = require("node-fetch");
(async () => {
const response = await fetch("https://stackoverflow.com/users/2614364", {
redirect: "manual",
});
console.log(response.status);
console.log(response.headers.get("set-cookie"));
})();
我想你想使用response.headers.get("set-cookie")
推荐阅读
- r - 具有分类数据的泊松 GLM
- swift - 我可以将字符串转换为 SINCall 吗?
- apache-spark - Spark 存储级别“NONE”与“MEMORY_ONLY”
- asp.net - 触发保存事件时,添加到 gridview 的行不会持续存在
- python - python中字典中的函数
- azure-active-directory - Saml 响应发送到应用注册下的默认回复 URL
- rcpp - 使用 Rcpp 时仅使用正数的计算返回负数
- ruby - ruby openssl smime 加密
- safari - Safari HTML5 视频不再自动播放
- php - opencart 2.1.0.2-save percent in category.php & 分页/过滤器问题