Twitter 的身份验证问题 API
Authentication issues with the Twitter API
我正在尝试在我的网站上显示 Twitter 帐户的最新推文,并且我正在尝试使用 cURL 和 PHP 获取数据。当我在 Twitter Developers 网站上使用 OAuth 工具(签名生成器)时。生成了一个 cURL 命令,它在我的终端上运行得很好。但是,当我尝试在我的 PHP 代码中使用具有相同参数的 cURL 时,出现以下错误:
{
"errors": [
{
"code": 215,
"message": "Bad Authentication data."
}
]
}
这是 cURL 命令:
curl --get 'https://api.twitter.com/1.1/statuses/user_timeline.json' --data 'count=2&screen_name=[my user name]' --header 'Authorization: OAuth oauth_consumer_key="[my key]", oauth_nonce="[my key]", oauth_signature="[the signature]", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1439736924", oauth_version="1.0"' --verbose
这是我的 PHP 代码:
$ch = curl_init("https://api.twitter.com/1.1/statuses/user_timeline.json?count=2&screen_name=XXXXX");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Authorization' => 'OAuth',
'oauth_consumer_key' => '[my key]',
'oauth_nonce' => '[my key]',
'oauth_signature' => '[the signature]',
'oauth_signature_method' => 'HMAC-SHA1',
'oauth_timestamp' => '1439736924',
'oauth_version' => '1.0')
);
curl_setopt($ch, CURLOPT_POSTFIELDS, array(
'count' => 2,
'screen_name' => '[my username]')
);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
echo curl_exec($ch);
值完全相同,我不明白为什么它适用于 curl 命令但不适用于 PHP 代码。这是两个日志:
cURL 命令(工作正常):
* Connected to api.twitter.com (199.16.156.199) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs/
* TLSv1.2, TLS handshake, Client hello (1):
* TLSv1.2, TLS handshake, Server hello (2):
* TLSv1.2, TLS handshake, CERT (11):
* TLSv1.2, TLS handshake, Server key exchange (12):
* TLSv1.2, TLS handshake, Server finished (14):
* TLSv1.2, TLS handshake, Client key exchange (16):
* TLSv1.2, TLS change cipher, Client hello (1):
* TLSv1.2, TLS handshake, Finished (20):
* TLSv1.2, TLS change cipher, Client hello (1):
* TLSv1.2, TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* Server certificate:
* subject: C=US; ST=California; L=San Francisco; O=Twitter, Inc.; OU=Twitter Security; CN=api.twitter.com
* start date: 2014-08-03 00:00:00 GMT
* expire date: 2016-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)10; CN=VeriSign Class 3 Secure Server CA - G3
* SSL certificate verify ok.
> GET /1.1/statuses/user_timeline.json?count=2&screen_name=XXX HTTP/1.1
> User-Agent: curl/7.38.0
> Host: api.twitter.com
> Accept: */*
> Authorization: OAuth oauth_consumer_key="BBBBBB", oauth_nonce="CCCCCCCC", oauth_signature="DDDDDDDD", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1439736924", oauth_version="1.0"
>
< HTTP/1.1 200 OK
< cache-control: no-cache, no-store, must-revalidate, pre-check=0, post-check=0
< content-disposition: attachment; filename=json.json
< content-length: 7512
< content-type: application/json;charset=utf-8
< date: Sun, 16 Aug 2015 16:09:46 GMT
< expires: Tue, 31 Mar 1981 05:00:00 GMT
< last-modified: Sun, 16 Aug 2015 16:09:46 GMT
< pragma: no-cache
< server: tsa_b
< set-cookie: guest_id=v1%3A143974138658672554; Domain=.twitter.com; Path=/; Expires=Tue, 15-Aug-2017 16:09:46 UTC
< status: 200 OK
< strict-transport-security: max-age=631138519
< x-connection-hash: ae1b9fcc59bb90b767b246dfd06f6c94
< x-content-type-options: nosniff
< x-frame-options: SAMEORIGIN
< x-rate-limit-limit: 300
< x-rate-limit-remaining: 298
< x-rate-limit-reset: 1439741812
< x-response-time: 23
< x-transaction: 8515dfd151751885
< x-twitter-response-tags: BouncerCompliant
< x-xss-protection: 1; mode=block
<
PHP 日志(returns 错误信息):
* Hostname in DNS cache was stale, zapped
* Trying 199.16.156.199...
* Connected to api.twitter.com (199.16.156.199) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs/
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* Server certificate:
* subject: C=US; ST=California; L=San Francisco; O=Twitter, Inc.; OU=Twitter Security; CN=api.twitter.com
* start date: 2014-08-03 00:00:00 GMT
* expire date: 2016-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)10; CN=VeriSign Class 3 Secure Server CA - G3
* SSL certificate verify ok.
> GET /1.1/statuses/user_timeline.json?count=2&screen_name=XXXX HTTP/1.1
Host: api.twitter.com
Accept: */*
Authorization: OAuth
oauth_consumer_key: BBBBBB
oauth_nonce: CCCCCCC
oauth_signature: DDDDDDD
oauth_signature_method: HMAC-SHA1
oauth_timestamp: 1439740787
oauth_version: 1.0
< HTTP/1.1 400 Bad Request
< content-length: 62
< content-type: application/json; charset=utf-8
< date: Sun, 16 Aug 2015 16:26:50 GMT
< server: tsa_b
< set-cookie: guest_id=v1%3A143974241022741403; Domain=.twitter.com; Path=/; Expires=Tue, 15-Aug-2017 16:26:50 UTC
< strict-transport-security: max-age=631138519
< x-connection-hash: abbabb47dc8a7d355f595f389f868de2
< x-response-time: 4
<
* Connection #0 to host api.twitter.com left intact
如有任何帮助,我们将不胜感激。如果可能的话,我真的很想使用 cURL 而不是第三方库。
谢谢
编辑:Michael 的解决方案无效,但这是更新后的 PHP 输出:
Authorization: OAuth oauth_consumer_key="...", oauth_nonce="...", oauth_signature="...", oauth_signature_method="HMAC-SHA1" oauth_timestamp= "1439744503", oauth_version= "1.0"
它们之间的主要区别在于,在 CLI curl
命令中,Authorization
header 被指定为 单个字符串 多个 key=value
对,以逗号分隔。但是在您的 PHP 代码中,您已将那些 key=value
对指定为 多个个体 headers。您只需添加一个 Authorization
header 并将所有这些值连接成一个字符串。
CLI 请求的 header 输出:
Authorization: OAuth oauth_consumer_key="BBBBBB", oauth_nonce="CCCCCCCC", oauth_signature="DDDDDDDD", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1439736924", oauth_version="1.0"
PHP 请求的 header 输出不同:
Authorization: OAuth
oauth_consumer_key: BBBBBB
oauth_nonce: CCCCCCC
oauth_signature: DDDDDDD
oauth_signature_method: HMAC-SHA1
oauth_timestamp: 1439740787
oauth_version: 1.0
因此,生成可比较的 single-header 字符串的正确 PHP 应该是:
curl_setopt($ch, CURLOPT_HEADER, 0);
// All OAuth values in a single Authorization header string.
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Authorization' => 'OAuth oauth_consumer_key="[my key]", oauth_nonce="[my key]", oauth_signature="[the signature]", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1439736924", oauth_version="1.0"'
)
);
// etc... Everything else should be fine as you have it
我正在尝试在我的网站上显示 Twitter 帐户的最新推文,并且我正在尝试使用 cURL 和 PHP 获取数据。当我在 Twitter Developers 网站上使用 OAuth 工具(签名生成器)时。生成了一个 cURL 命令,它在我的终端上运行得很好。但是,当我尝试在我的 PHP 代码中使用具有相同参数的 cURL 时,出现以下错误:
{
"errors": [
{
"code": 215,
"message": "Bad Authentication data."
}
]
}
这是 cURL 命令:
curl --get 'https://api.twitter.com/1.1/statuses/user_timeline.json' --data 'count=2&screen_name=[my user name]' --header 'Authorization: OAuth oauth_consumer_key="[my key]", oauth_nonce="[my key]", oauth_signature="[the signature]", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1439736924", oauth_version="1.0"' --verbose
这是我的 PHP 代码:
$ch = curl_init("https://api.twitter.com/1.1/statuses/user_timeline.json?count=2&screen_name=XXXXX");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Authorization' => 'OAuth',
'oauth_consumer_key' => '[my key]',
'oauth_nonce' => '[my key]',
'oauth_signature' => '[the signature]',
'oauth_signature_method' => 'HMAC-SHA1',
'oauth_timestamp' => '1439736924',
'oauth_version' => '1.0')
);
curl_setopt($ch, CURLOPT_POSTFIELDS, array(
'count' => 2,
'screen_name' => '[my username]')
);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
echo curl_exec($ch);
值完全相同,我不明白为什么它适用于 curl 命令但不适用于 PHP 代码。这是两个日志:
cURL 命令(工作正常):
* Connected to api.twitter.com (199.16.156.199) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs/
* TLSv1.2, TLS handshake, Client hello (1):
* TLSv1.2, TLS handshake, Server hello (2):
* TLSv1.2, TLS handshake, CERT (11):
* TLSv1.2, TLS handshake, Server key exchange (12):
* TLSv1.2, TLS handshake, Server finished (14):
* TLSv1.2, TLS handshake, Client key exchange (16):
* TLSv1.2, TLS change cipher, Client hello (1):
* TLSv1.2, TLS handshake, Finished (20):
* TLSv1.2, TLS change cipher, Client hello (1):
* TLSv1.2, TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* Server certificate:
* subject: C=US; ST=California; L=San Francisco; O=Twitter, Inc.; OU=Twitter Security; CN=api.twitter.com
* start date: 2014-08-03 00:00:00 GMT
* expire date: 2016-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)10; CN=VeriSign Class 3 Secure Server CA - G3
* SSL certificate verify ok.
> GET /1.1/statuses/user_timeline.json?count=2&screen_name=XXX HTTP/1.1
> User-Agent: curl/7.38.0
> Host: api.twitter.com
> Accept: */*
> Authorization: OAuth oauth_consumer_key="BBBBBB", oauth_nonce="CCCCCCCC", oauth_signature="DDDDDDDD", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1439736924", oauth_version="1.0"
>
< HTTP/1.1 200 OK
< cache-control: no-cache, no-store, must-revalidate, pre-check=0, post-check=0
< content-disposition: attachment; filename=json.json
< content-length: 7512
< content-type: application/json;charset=utf-8
< date: Sun, 16 Aug 2015 16:09:46 GMT
< expires: Tue, 31 Mar 1981 05:00:00 GMT
< last-modified: Sun, 16 Aug 2015 16:09:46 GMT
< pragma: no-cache
< server: tsa_b
< set-cookie: guest_id=v1%3A143974138658672554; Domain=.twitter.com; Path=/; Expires=Tue, 15-Aug-2017 16:09:46 UTC
< status: 200 OK
< strict-transport-security: max-age=631138519
< x-connection-hash: ae1b9fcc59bb90b767b246dfd06f6c94
< x-content-type-options: nosniff
< x-frame-options: SAMEORIGIN
< x-rate-limit-limit: 300
< x-rate-limit-remaining: 298
< x-rate-limit-reset: 1439741812
< x-response-time: 23
< x-transaction: 8515dfd151751885
< x-twitter-response-tags: BouncerCompliant
< x-xss-protection: 1; mode=block
<
PHP 日志(returns 错误信息):
* Hostname in DNS cache was stale, zapped
* Trying 199.16.156.199...
* Connected to api.twitter.com (199.16.156.199) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs/
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* Server certificate:
* subject: C=US; ST=California; L=San Francisco; O=Twitter, Inc.; OU=Twitter Security; CN=api.twitter.com
* start date: 2014-08-03 00:00:00 GMT
* expire date: 2016-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)10; CN=VeriSign Class 3 Secure Server CA - G3
* SSL certificate verify ok.
> GET /1.1/statuses/user_timeline.json?count=2&screen_name=XXXX HTTP/1.1
Host: api.twitter.com
Accept: */*
Authorization: OAuth
oauth_consumer_key: BBBBBB
oauth_nonce: CCCCCCC
oauth_signature: DDDDDDD
oauth_signature_method: HMAC-SHA1
oauth_timestamp: 1439740787
oauth_version: 1.0
< HTTP/1.1 400 Bad Request
< content-length: 62
< content-type: application/json; charset=utf-8
< date: Sun, 16 Aug 2015 16:26:50 GMT
< server: tsa_b
< set-cookie: guest_id=v1%3A143974241022741403; Domain=.twitter.com; Path=/; Expires=Tue, 15-Aug-2017 16:26:50 UTC
< strict-transport-security: max-age=631138519
< x-connection-hash: abbabb47dc8a7d355f595f389f868de2
< x-response-time: 4
<
* Connection #0 to host api.twitter.com left intact
如有任何帮助,我们将不胜感激。如果可能的话,我真的很想使用 cURL 而不是第三方库。
谢谢
编辑:Michael 的解决方案无效,但这是更新后的 PHP 输出:
Authorization: OAuth oauth_consumer_key="...", oauth_nonce="...", oauth_signature="...", oauth_signature_method="HMAC-SHA1" oauth_timestamp= "1439744503", oauth_version= "1.0"
它们之间的主要区别在于,在 CLI curl
命令中,Authorization
header 被指定为 单个字符串 多个 key=value
对,以逗号分隔。但是在您的 PHP 代码中,您已将那些 key=value
对指定为 多个个体 headers。您只需添加一个 Authorization
header 并将所有这些值连接成一个字符串。
CLI 请求的 header 输出:
Authorization: OAuth oauth_consumer_key="BBBBBB", oauth_nonce="CCCCCCCC", oauth_signature="DDDDDDDD", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1439736924", oauth_version="1.0"
PHP 请求的 header 输出不同:
Authorization: OAuth
oauth_consumer_key: BBBBBB
oauth_nonce: CCCCCCC
oauth_signature: DDDDDDD
oauth_signature_method: HMAC-SHA1
oauth_timestamp: 1439740787
oauth_version: 1.0
因此,生成可比较的 single-header 字符串的正确 PHP 应该是:
curl_setopt($ch, CURLOPT_HEADER, 0);
// All OAuth values in a single Authorization header string.
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Authorization' => 'OAuth oauth_consumer_key="[my key]", oauth_nonce="[my key]", oauth_signature="[the signature]", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1439736924", oauth_version="1.0"'
)
);
// etc... Everything else should be fine as you have it