Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/264.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php TwitterAPI 1.1在搜索包含以下内容时返回身份验证错误@&引用;性格_Php_Twitter - Fatal编程技术网

Php TwitterAPI 1.1在搜索包含以下内容时返回身份验证错误@&引用;性格

Php TwitterAPI 1.1在搜索包含以下内容时返回身份验证错误@&引用;性格,php,twitter,Php,Twitter,如果我将test传递给tweets.json端点的q参数,它将返回数据。但是如果我在前面包含@符号,即@test,我会得到以下错误: 无法验证您的身份 当我使用%40而不是@时,同样的问题也会发生 这是我的密码: $query = array( // query parameters 'q' => '@test', 'count' => '100' ); $method = "GET"; $path = "/1.1/search/tweets.json"; $to

如果我将
test
传递给
tweets.json
端点的
q
参数,它将返回数据。但是如果我在前面包含
@
符号,即
@test
,我会得到以下错误:

无法验证您的身份

当我使用
%40
而不是
@
时,同样的问题也会发生

这是我的密码:

$query = array( // query parameters
    'q' => '@test',
    'count' => '100'
);

$method = "GET";
$path = "/1.1/search/tweets.json";

$token = 'xxxxxx';
$token_secret = 'xxxxxx';
$consumer_key = 'xxxxxxx';
$consumer_secret = 'xxxxxx';

$host = 'api.twitter.com';

$oauth = array(
    'oauth_consumer_key' => $consumer_key,
    'oauth_token' => $token,
    'oauth_nonce' => (string)mt_rand(), // a stronger nonce is recommended
    'oauth_timestamp' => time(),
    'oauth_signature_method' => 'HMAC-SHA1',
    'oauth_version' => '1.0'
);

$oauth = array_map("rawurlencode", $oauth); // must be encoded before sorting
$query = array_map("rawurlencode", $query);

$arr = array_merge($oauth, $query); // combine the values THEN sort

asort($arr); // secondary sort (value)
ksort($arr); // primary sort (key)

// http_build_query automatically encodes, but our parameters
// are already encoded, and must be by this point, so we undo
// the encoding step
$querystring = urldecode(http_build_query($arr, '', '&'));

$url = "https://$host$path";

// mash everything together for the text to hash
$base_string = $method."&".rawurlencode($url)."&".rawurlencode($querystring);

// same with the key
$key = rawurlencode($consumer_secret)."&".rawurlencode($token_secret);

// generate the hash
$signature = rawurlencode(base64_encode(hash_hmac('sha1', $base_string, $key, true)));

// this time we're using a normal GET query, and we're only encoding the query params
// (without the oauth params)
$url .= "?".http_build_query($query);
$url=str_replace("&","&",$url); //Patch by @Frewuill

$oauth['oauth_signature'] = $signature; // don't want to abandon all that work!
ksort($oauth); // probably not necessary, but twitter's demo does it

// also not necessary, but twitter's demo does this too
function add_quotes($str) { return '"'.$str.'"'; }
$oauth = array_map("add_quotes", $oauth);

// this is the full value of the Authorization line
$auth = "OAuth " . urldecode(http_build_query($oauth, '', ', '));

// if you're doing post, you need to skip the GET building above
// and instead supply query parameters to CURLOPT_POSTFIELDS
$options = array( CURLOPT_HTTPHEADER => array("Authorization: $auth"),
                  //CURLOPT_POSTFIELDS => $postfields,
                  CURLOPT_HEADER => false,
                  CURLOPT_URL => $url,
                  CURLOPT_RETURNTRANSFER => true,
                  CURLOPT_SSL_VERIFYPEER => false);

// do our business
$feed = curl_init();
curl_setopt_array($feed, $options);
$json = curl_exec($feed);
curl_close($feed);

return $json;

为什么我不能用
@
符号在
q
参数前面检索数据?

正如我所怀疑的,这是一个双重(甚至三重)编码问题。我设法使它以两种不同的方式工作(它们不能一起使用):

  • rawurlencode()
    之前进行合并,我的首选解决方案:

    //NOPE $oauth = array_map("rawurlencode", $oauth); // must be encoded before sorting
    //NOPE $query = array_map("rawurlencode", $query);
    
    $arr = array_merge($oauth, $query); // combine the values THEN sort
    $arr = array_map("rawurlencode", $arr);
    
    asort($arr); // secondary sort (value)
    ksort($arr); // primary sort (key)
    
  • 在http\u build\u query()之后删除
    urldecode()

  • 但在这一点上,我无法解释为什么这两种方法都有效。事实证明,在代码的后面,您将使用以下内容:

    // this time we're using a normal GET query, and we're only encoding the query params
    // (without the oauth params)
    $url .= "?".http_build_query($query);
    
    微妙的区别在于这次在
    http\u build\u query()
    之后没有使用
    urldecode()

    由于进行了所有的编码,因此最终用于签名的url与用于请求的url不匹配,因此身份验证失败

    签名
    oauth\u signature
    参数包含一个值,该值是通过运行所有其他请求参数和通过签名算法生成的两个秘密值生成的。签名的目的是让Twitter能够验证请求在传输过程中没有被修改,验证发送请求的应用程序,以及验证应用程序有权与用户帐户交互

    这样,url编码2次,签名url编码3次:

    // end of $url, encoded twice
    ?q=%2540test&count=100
    // end of $base_string, used in signature, encoded thrice
    %26oauth_version%3D1.0%26q%3D%252540test
    
    // end of $url
    ?q=%40test&count=100
    // end of $base_string, used in signature
    %26oauth_version%3D1.0%26q%3D%252540test
    
    否则,url编码1次,签名url编码3次:

    // end of $url, encoded twice
    ?q=%2540test&count=100
    // end of $base_string, used in signature, encoded thrice
    %26oauth_version%3D1.0%26q%3D%252540test
    
    // end of $url
    ?q=%40test&count=100
    // end of $base_string, used in signature
    %26oauth_version%3D1.0%26q%3D%252540test
    
    由于签名只能比请求url多编码一次,因此前面提到的两种解决方案都可以(独立)工作,因为:

    • 解决方案1不编码
      $query
      ,使
      $url
      单编码,签名双编码
    • 解决方案2保留双重编码,保留
      $url
      双重编码,并使签名三重编码
    但是等等,为什么只有在使用
    @
    时才会失败


    因为这是所有参数中唯一需要编码的字符。当使用
    http\u build\u query()
    ,生成一个
    %
    字符,该字符将在随后的编码中被捕获时,对其进行编码。

    @test实际上是在搜索“引用人”测试。请看:是的,这个想法是为了获得有问题的“引用人”的tweet。这似乎更多的是代码问题,而不是twitter问题。添加
    @
    会导致连接错误,这似乎很奇怪。另外,如果你正在寻找一个人,为什么不访问魔兽世界谢谢你的回答。我尝试了你的第一个解决方案,效果很好。我告诉你,他们不能让调用API变得比实际情况更复杂。两小时后,如果stackoverflow允许,我会给你+50