Twitter 搜索 API:通过 HTTParty “未经授权”,但通过 Curl 成功

Posted

技术标签:

【中文标题】Twitter 搜索 API:通过 HTTParty “未经授权”,但通过 Curl 成功【英文标题】:Twitter search API: "Unauthorized" through HTTParty but successful via Curl 【发布时间】:2013-06-05 05:52:48 【问题描述】:

在我们的 Rails 应用程序上工作时,我尝试通过 HTTParty 使用搜索 API v1.1 检索推文。我已经仔细完成了所有步骤,并使用 Twitter 示例对我们的代码进行了单元测试,以设置正确的 OAuth 授权,因此我非常有信心所有代码都能正常工作。但是,无论我尝试什么,我都会不断收到 ""errors":["message":"Could not authenticate you","code":32]"" 回复。

使用 OAuth 工具,我生成了我需要的请求。我将 nonce 和时间戳粘贴到我的代码中,以在我们的应用程序中复制完全相同的请求。这是生成的日志:

opening connection to api.twitter.com...
opened
<- "GET /1.1/search/tweets.json?q=from:plindelauf&include_entities=true HTTP/1.1\r\nAuthorization: OAuth oauth_consumer_key=\"DOP3re9nlTPeyemlmcqg\", oauth_nonce=\"05d29110d282b24e516dae1ae2b54e1a\", oauth_signature=\"k9gHhrHD86D5sB7zAlXCKsaeNZ8%3D\", oauth_signature_method=\"HMAC-SHA1\", oauth_timestamp=\"1370691632\", oauth_token=\"288762088-DfqCgEIVvM56MSMZWjLuLl6oo3oaVkI0Z8ATKu3f\", oauth_version=\"1.0\"\r\nConnection: close\r\nHost: api.twitter.com\r\n\r\n"
-> "HTTP/1.1 401 Unauthorized\r\n"
-> "content-length: 63\r\n"
-> "content-type: application/json; charset=utf-8\r\n"
-> "date: Sat, 08 Jun 2013 11:41:41 UTC\r\n"
-> "server: tfe\r\n"
-> "set-cookie: guest_id=v1%3A137069170192515887; Domain=.twitter.com; Path=/; Expires=Mon, 08-Jun-2015 11:41:41 UTC\r\n"
-> "strict-transport-security: max-age=631138519\r\n"
-> "Connection: close\r\n"
-> "\r\n"
reading 63 bytes...
-> ""
-> "\"errors\":[\"message\":\"Could not authenticate you\",\"code\":32]"
read 63 bytes
Conn close

请注意,即使上面的转储没有显示它,我已经验证了请求是通过 https 发送的。

然后从 OAuth 工具执行 CURL 命令就可以了:

curl --get 'https://api.twitter.com/1.1/search/tweets.json' --data 'include_entities=true&q=from%3Aplindelauf' --header 'Authorization: OAuth oauth_consumer_key="DOP3re9nlTPeyemlmcqg", oauth_nonce="05d29110d282b24e516dae1ae2b54e1a", oauth_signature="k9gHhrHD86D5sB7zAlXCKsaeNZ8%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1370691632", oauth_token="288762088-DfqCgEIVvM56MSMZWjLuLl6oo3oaVkI0Z8ATKu3f", oauth_version="1.0"' --verbose
* About to connect() to api.twitter.com port 443 (#0)
*   Trying 199.16.156.8...
* connected
* Connected to api.twitter.com (199.16.156.8) port 443 (#0)
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSL connection using RC4-SHA
* Server certificate:
*    subject: C=US; ST=California; L=San Francisco; O=Twitter, Inc.; OU=Twitter Security; CN=api.twitter.com
*    start date: 2013-04-08 00:00:00 GMT
*    expire date: 2013-12-31 23:59:59 GMT
*    subjectAltName: api.twitter.com matched
*    issuer: C=US; O=VeriSign, Inc.; OU=VeriSign Trust Network; OU=Terms of use at https://www.verisign.com/rpa (c)09; CN=VeriSign Class 3 Secure Server CA - G2
*    SSL certificate verify ok.
> GET /1.1/search/tweets.json?include_entities=true&q=from%3Aplindelauf HTTP/1.1
> User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8r zlib/1.2.5
> Host: api.twitter.com
> Accept: */*
> Authorization: OAuth oauth_consumer_key="DOP3re9nlTPeyemlmcqg", oauth_nonce="05d29110d282b24e516dae1ae2b54e1a", oauth_signature="k9gHhrHD86D5sB7zAlXCKsaeNZ8%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1370691632", oauth_token="288762088-DfqCgEIVvM56MSMZWjLuLl6oo3oaVkI0Z8ATKu3f", oauth_version="1.0"
> 
< HTTP/1.1 200 OK
< cache-control: no-cache, no-store, must-revalidate, pre-check=0, post-check=0
< content-length: 14040
< content-type: application/json;charset=utf-8
< date: Sat, 08 Jun 2013 11:42:20 GMT
< expires: Tue, 31 Mar 1981 05:00:00 GMT
< last-modified: Sat, 08 Jun 2013 11:42:20 GMT
< pragma: no-cache
< server: tfe
< set-cookie: lang=en
< set-cookie: guest_id=v1%3A137069174010710877; Domain=.twitter.com; Path=/; Expires=Mon, 08-Jun-2015 11:42:20 UTC
< status: 200 OK
< strict-transport-security: max-age=631138519
< x-access-level: read
< x-frame-options: SAMEORIGIN
< x-rate-limit-limit: 180
< x-rate-limit-remaining: 179
< x-rate-limit-reset: 1370692640
< x-transaction: 4b4022555f454e2b
< x-xss-protection: 1; mode=block
...[the whole response body with all found tweets]...

我也尝试过单独发送查询参数时是否有所不同,但似乎并非如此,因为此 curl 命令也可以正常工作:

curl --get 'https://api.twitter.com/1.1/search/tweets.json?include_entities=true&q=from%3Aplindelauf' --header 'Authorization: OAuth oauth_consumer_key="DOP3re9nlTPeyemlmcqg", oauth_nonce="05d29110d282b24e516dae1ae2b54e1a", oauth_signature="k9gHhrHD86D5sB7zAlXCKsaeNZ8%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1370691632", oauth_token="288762088-DfqCgEIVvM56MSMZWjLuLl6oo3oaVkI0Z8ATKu3f", oauth_version="1.0"' --verbose

这已经让我发疯了很多天了!有人可以帮忙吗?!

【问题讨论】:

【参考方案1】:

我发现了问题!我没有像创建签名时那样对 HTTP 请求中的查询参数进行百分比编码。请注意,我发送的是查询字符串q=from:plindelauf&amp;include_entities=true。这需要明确地是include_entities=true&amp;q=from%3Aplindelauf。该死!

【讨论】:

您能分享一下您是如何确保查询参数是百分比编码的吗?我正在尝试将 JSON blob 传递给端点,我认为这是缺少的部分 当然:full_url = base_uri + URI.encode(path)。 full_url 然后作为所有处理documented by Twitter 的基础。希望这会有所帮助。

以上是关于Twitter 搜索 API:通过 HTTParty “未经授权”,但通过 Curl 成功的主要内容,如果未能解决你的问题,请参考以下文章

Twitter:标签搜索查询

如何使用Twitter API获取某些国家/地区的所有推文?

如何解决 Twitter 搜索 API 2.0 上的操作员错误

Twitter 搜索 API 响应?

使用 Twitter 搜索 API 的位置和 OAuth 问题

使用 Google Apps 脚本和 Twitter API 搜索 Twitter 句柄 - 不起作用