问题描述
当我尝试在沙箱 (https://apisb.eTrade.com/v1/accounts/list
) 中向 ETrade 的 Account List 端点发出请求时,我收到 HTTP 401 -“未经授权的请求 - 无效的消费者密钥和/或会话令牌”。
我不明白为什么这个请求不起作用,因为我成功调用了 Get Access Token API,检索了 oauth_token
和 oauth_token_secret
并使用它们来签署和发出请求到帐户列表。
更让我困惑的是,我下载了官方的 Etrade Python Client,在调用帐户列表之前放置了一个断点,并确认我的代码在给定相同的请求参数的情况下生成了完全相同的 oauth_signature
.
此外,我实际上复制了官方 Python 客户端生成的所有请求参数并将它们粘贴到我的网络浏览器中,但仍然收到相同的“未经授权的请求 - 无效的消费者密钥和/或会话令牌”响应。>
为了说明,这里是我在官方 Python 客户端中放置的断点(我已将敏感键的前四个字母替换为“123a”):
Breakpoint 1 at /Users/me/Downloads/ETradePythonClient/venv/lib/python3.9/site-packages/rauth/session.py:210
(Pdb) c
> /Users/me/Downloads/ETradePythonClient/venv/lib/python3.9/site-packages/rauth/session.py(210)request()
-> return super(OAuth1Session,self).request(method,url,**req_@R_404_4868@)
(Pdb) pprint.pprint(oauth_params)
{'oauth_consumer_key': '123a01814e407344bc2b385f3954679b','oauth_nonce': '8230791e8c0253518a6b2dec8120b643fde93745','oauth_signature': '123apxtEaUJmlvKFWv7zz+lfNk4=','oauth_signature_method': 'HMAC-SHA1','oauth_timestamp': 1614559929,'oauth_token': '123aMSpwaaWItBDgXQ/Te4M9363WSULWFdeHkh18B8s=','oauth_version': '1.0'}
(Pdb) url
'https://apisb.eTrade.com/v1/accounts/list.json'
(Pdb) method
'GET'
使用上述内容,我构建了以下 URL 并将其粘贴到我的网络浏览器中:
https://apisb.eTrade.com/v1/accounts/list.json?oauth_consumer_key=123a01814e407344bc2b385f3954679b&oauth_nonce=8230791e8c0253518a6b2dec8120b643fde93745&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1614559929&oauth_token=123aMSpwaaWItBDgXQ/Te4M9363WSULWFdeHkh18B8s=&oauth_version=1.0&oauth_signature=123apxtEaUJmlvKFWv7zz+lfNk4=
但我收到 HTTP 401 响应 -“未经授权的请求 - 无效的消费者密钥和/或会话令牌”。
然而,该请求在官方 Python 客户端中有效(只要我不先在浏览器中尝试,否则我将在 Python 客户端中收到“错误:oauth_problem=nonce_used”错误)。>
我注意到的一件事是官方 Python 客户端添加了 oauth_version=1.0
参数,但无论我是否包含该参数并使用它签名,我的请求仍然失败。
我还注意到官方 Python 客户端向 url 添加了 .json
,但无论是否包含 .json
,我仍然收到未经授权的错误。
我还尝试将 OAuth 参数作为 HTTP 标头而不是 URL 参数发送,但我仍然遇到相同的错误。
我还在我的请求中对 URL 参数进行了 rfc3986 编码(百分比编码),这适用于获取访问令牌请求,但不适用于帐户列表请求。
请注意,我将以下 URL 用于请求令牌、访问令牌和沙盒 API:
https://apisb.eTrade.com/oauth/request_token
https://us.eTrade.com/e/t/etws/authorize?key=${oauth_consumer_key}&token=${state.oauth_token}
https://apisb.eTrade.com/oauth/access_token
https://apisb.eTrade.com/v1/accounts/list
我还能尝试调试什么?
解决方法
想通了:
问题在于,由于我从网络浏览器(Chrome 扩展程序)发送请求,我的请求包含 Cookie,这导致 API 产生会话错误。
我正在使用 Fetch API。
在 {"credentials": "omit"}
参数中设置 init
会忽略 Cookie 标头并解决问题。