【问题标题】:What could be different in https implementation for python vs nodejs?python vs nodejs的https实现有什么不同?
【发布时间】:2020-11-14 10:09:46
【问题描述】:

我正试图找出一个奇怪的问题。我有工作 python 代码,我想翻译成 NodeJS。 Python 代码非常简单且有效:

import requests

LOGIN_URL = 'https://android.clients.google.com/auth'
params = {'Email': '***', 'EncryptedPasswd': b'***', 'service': 'androidmarket', 'accountType': 'HOSTED_OR_GOOGLE', 'has_permission': 1, 'source': 'android', 'device_country': 'us', 'lang': 'us'}
response = requests.post(LOGIN_URL, data=params, verify=True)
print(response.text)

这是 NodeJS 版本代码:

const request = require('request');

const LOGIN_URL = 'https://android.clients.google.com/auth'
const params = {'Email': '***', 'EncryptedPasswd': '***', 'service': 'androidmarket', 'accountType': 'HOSTED_OR_GOOGLE', 'has_permission': 1, 'source': 'android', 'device_country': 'us', 'lang': 'us'}
request({url: LOGIN_URL, method: 'POST', form: params}, function(error, response) {
   console.log(response.statusCode);
});

这不起作用,我正在返回 403 - 错误请求。 我尝试将协议更改为 http,然后在 Wireshark 中检查数据包内容。它们几乎相同,只是略有不同。我尝试通过覆盖 NodeJS 版本中的标头来消除所有差异,但没有帮助。所以我的猜测是https有问题?

我错过了什么? Python 和 NodeJS 之间可能有什么区别?

【问题讨论】:

  • 在两个代码中都使用 url httpbin.org/post,然后你会返回(作为 JSON 数据)所有听众、cookie 等发送到这个 url - 然后你可以比较 Python 和 NodeJS 的结果。跨度>
  • 最终使用一些本地代理服务器,如 Charles ProxyMan-In-The-Middle Proxy(在 Python 中创建)并在两个连接中使用它们来查看所有发送到服务器的数据 - 然后你可以比较它们。跨度>
  • 您也可以使用postmaninsomnia 来测试url - 两者都具有生成不同语言代码的功能 - 即。 PythonNodeJS
  • @furas 我已经通过 Wireshark 测试了 HTTP 请求内容,并且能够为 Python 和 NodeJS 实现相同的内容。
  • @momo 但这似乎没有任何区别。当我在 Wireshark 的 http 请求中看到这一点时,它们是相同的,因为 EncryptedPasswd 作为字符串发送。

标签: python node.js http


【解决方案1】:

第二次猜测:

登录需要 cookie,NodeJS requests 默认禁用 cookie。试试:

const request = request.defaults({jar: true})

第一个猜测:

发布的python代码和Node.js代码的区别:

  • python 代码发送这些标头:
HTTP_ACCEPT: */*
HTTP_ACCEPT_ENCODING: gzip, deflate
HTTP_CONNECTION: keep-alive
HTTP_USER_AGENT: python-requests/2.24.0
  • Node 代码仅发送以下标头:
HTTP_CONNECTION: close

很可能是标头有问题,但也可能是 Python 代码可以访问 cookie jar 并且正在向请求中添加 cookie,而 Node.JS 代码没有。

另一种可能性是您的两个客户端正在使用两个不同的 TLS 堆栈(或至少 2 个不同的配置),并且 NodeJS 客户端无法协商可接受的密码。

我建议您使用 Postman 之类的工具手动尝试各种请求,以确定哪些有效,哪些无效。如果你让它在 Postman 中工作,使用 Postman 导出 Python 和 NodeJS 的代码 sn-ps 并确认它们工作。如果导出的代码在 Python 中工作,但在 NodeJS 中不工作,那么问题不在代码上。

问题很可能是您没有意识到的,因此没有告诉我们。让 Postman 也导出 curlwget 命令,这样您就可以验证它们是否在您的 Docker 容器中工作,并且问题不在于容器或 Docker 网络。使用 curl -v 查看正在协商的 TLS 密码,并将 NodeJS 配置为仅使用该版本的 TLS 和仅使用该密码,因为 Google 喜欢阻止允许降级到旧的损坏 TLS 版本或弱密码的客户端。

【讨论】:

  • 对不起,如果我没有清楚地描述它,但我确实尝试更改 NodeJS 版本以发送完全相同的数据,包括所有标题。我在 Wireshark 中检查了发送的请求,它们看起来一模一样。
  • 我已经尝试过刚刚尝试过的 Postman,它也可以执行来自 Postman 的请求。然后我使用了“代码”功能。在 NodeJS 代码中导出请求,运行它,我仍然得到 403 - Bad request。
  • 我测试了所有标头的代码,甚至使用了不同的模块httpsfetch,我唯一的想法是问题出在较低级别 - 即。 SSL/TLS
  • @Aleksey 登录可能会执行需要 cookie 的重定向,但 NodeJS 默认禁用 cookie。我更新了我的答案。
  • @OldPro 我试过这个但没有用。还尝试通过请求显式传递 cookie jar,没有任何改变。如何验证是否正在进行重定向?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-02
  • 2020-01-03
  • 1970-01-01
  • 2012-03-24
  • 2012-05-21
相关资源
最近更新 更多