另一个失败的 twitter oAuth cURL 访问令牌请求

Posted

技术标签:

【中文标题】另一个失败的 twitter oAuth cURL 访问令牌请求【英文标题】:another twitter oAuth cURL access token request that fails 【发布时间】:2011-03-18 18:01:24 【问题描述】:

以下函数给出验证错误而不是令牌:

无法验证 oAuth 签名和令牌

 function request_token()
 
  // Set url
  $url = $this->site.$this->request_token_path; // http://api.twitter.com/oauth/request_token

  // Params to pass to twitter and create signature
     $params['oauth_consumer_key'] = $this->consumerKey;
     $params['oauth_token'] = '';
     $params['oauth_nonce'] = SHA1(time());
     $params['oauth_timestamp'] = time();
     $params['oauth_signature_method'] = $this->signatureMethod; // HMAC-SHA1;
     $params['oauth_version'] = $this->version; // 1.0
     ksort($params);

     //print "<pre>"; print_r($params); print "</pre>";

     // Create Signature
     $concatenatedParams = '';
     foreach($params as $k => $v)
      $concatenatedParams .= "$k=$v&"; 
     
     $concatenatedParams = substr($concatenatedParams,0,-1);

     $signatureBaseString = "POST&".urlencode($url)."&".urlencode($concatenatedParams);
     $params['oauth_signature'] = base64_encode(hash_hmac('SHA1', $signatureBaseString, $this->secret."&", TRUE));

  // Do cURL
  $ch = curl_init();
   curl_setopt($ch, CURLOPT_URL, $url);
   curl_setopt($ch, CURLINFO_HEADER_OUT, 0);
   curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
   curl_setopt($ch, CURLOPT_HEADER, 1);
   curl_setopt($ch, CURLOPT_POST, 1);
   curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
   curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
   curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);
   $exec = curl_exec ($ch);
   $info = curl_getinfo($ch);
  curl_close ($ch);

     print $exec;

    //print "<pre>"; print_r($info); print "</pre>";
 

【问题讨论】:

请注意。 Twitter 存在 oAuth 问题。这可能不是你的问题。 dev.twitter.com/status 谢谢 - 我不认为它... 【参考方案1】:

以下是我到目前为止汇总的内容:-)

    class Twitauth
    
      var $key = '';
      var $secret = '';

      var $request_token = "https://twitter.com/oauth/request_token";

    function Twitauth($config)
    
        $this->key = $config['key']; // consumer key from twitter
        $this->secret = $config['secret']; // secret from twitter
    

    function getRequestToken()
    
        // Default params
        $params = array(
            "oauth_version" => "1.0",
            "oauth_nonce" => time(),
            "oauth_timestamp" => time(),
            "oauth_consumer_key" => $this->key,
            "oauth_signature_method" => "HMAC-SHA1"
         );

         // BUILD SIGNATURE
            // encode params keys, values, join and then sort.
            $keys = $this->_urlencode_rfc3986(array_keys($params));
            $values = $this->_urlencode_rfc3986(array_values($params));
            $params = array_combine($keys, $values);
            uksort($params, 'strcmp');

            // convert params to string 
            foreach ($params as $k => $v) $pairs[] = $this->_urlencode_rfc3986($k).'='.$this->_urlencode_rfc3986($v);
            $concatenatedParams = implode('&', $pairs);

            // form base string (first key)
            $baseString= "GET&".$this->_urlencode_rfc3986($this->request_token)."&".$this->_urlencode_rfc3986($concatenatedParams);
            // form secret (second key)
            $secret = $this->_urlencode_rfc3986($this->secret)."&";
            // make signature and append to params
            $params['oauth_signature'] = $this->_urlencode_rfc3986(base64_encode(hash_hmac('sha1', $baseString, $secret, TRUE)));

         // BUILD URL
            // Resort
            uksort($params, 'strcmp');
            // convert params to string 
            foreach ($params as $k => $v) $urlPairs[] = $k."=".$v;
            $concatenatedUrlParams = implode('&', $urlPairs);
            // form url
            $url = $this->request_token."?".$concatenatedUrlParams;

         // Send to cURL
         print $this->_http($url);          
    

    function _http($url, $post_data = null)
           
        $ch = curl_init();

        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);

        if(isset($post_data))
        
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
        

        $response = curl_exec($ch);
        $this->http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $this->last_api_call = $url;
        curl_close($ch);

        return $response;
    

    function _urlencode_rfc3986($input)
    
        if (is_array($input)) 
            return array_map(array('Twitauth', '_urlencode_rfc3986'), $input);
        
        else if (is_scalar($input)) 
            return str_replace('+',' ',str_replace('%7E', '~', rawurlencode($input)));
        
        else
            return '';
        
    

【讨论】:

不错!它有效,在 getRequestToken 方法的末尾有一个“打印”而不是“返回”。 我正试图让这个东西在 C#(不懂 php)中工作,所以我有点困惑。是 var $secret,来自 twitter 的秘密消费者密钥吗? 我有点晚了,if (is_array($input)) return array_map(array('Twitauth', '_urlencode_rfc3986'), $input); 有什么意义 这不起作用,除非您按照***.com/a/4199002/389976 的附加说明进行操作 天哪!谢谢!我一直在寻找一个可以在不使用 cURL 的情况下使用的功能,我只是删除了 _http 函数中的所有内容并用 $response=file_get_contents($url) 替换它,令我惊讶的是,它起作用了!!【参考方案2】:

不确定您是否仍在研究此问题,或者它是否适合您,但我有类似的设置并且遇到了同样的问题。我最终发现我正在 urlencoding 一到多次。 尝试注释掉这部分:

 $keys = $this->_urlencode_rfc3986(array_keys($params));
        $values = $this->_urlencode_rfc3986(array_values($params));
        $params = array_combine($keys, $values);

为我工作,所以也许会有所帮助。

【讨论】:

***.com/users/195192/good-bye 应该修改他的帖子,感谢您对他的回答的洞察力!【参考方案3】:

我承认这不是一个真正的答案,但如果可以,请使用 PECL OAuth 包。 Rasmus Lerdorf wrote a tutorial on how to use it 它让我解决了同样的问题。

【讨论】:

【参考方案4】:

我遇到了同样的问题,我缺少的是将标头传递给 curl 请求。如这个问题所示,我还发送了 $header = array('Expect:'),这就是我的问题。我开始在标头中发送带有其他数据的签名,如下所示,它为我解决了这个问题。

$header = calculateHeader($parameters, 'https://api.twitter.com/oauth/request_token');

function calculateHeader(array $parameters, $url)
    
        // redefine
        $url = (string) $url;

        // divide into parts
        $parts = parse_url($url);

        // init var
        $chunks = array();

        // process queries
        foreach($parameters as $key => $value) $chunks[] = str_replace('%25', '%', urlencode_rfc3986($key) . '="' . urlencode_rfc3986($value) . '"');

        // build return
        $return = 'Authorization: OAuth realm="' . $parts['scheme'] . '://' . $parts['host'] . $parts['path'] . '", ';
        $return .= implode(',', $chunks);

        // prepend name and OAuth part
        return $return;
    

function urlencode_rfc3986($value)
    
        if(is_array($value)) return array_map('urlencode_rfc3986', $value);
        else
        
            $search = array('+', ' ', '%7E', '%');
            $replace = array('%20', '%20', '~', '%25');

            return str_replace($search, $replace, urlencode($value));
        
    

【讨论】:

以上是关于另一个失败的 twitter oAuth cURL 访问令牌请求的主要内容,如果未能解决你的问题,请参考以下文章

PHP 如何在没有oAuth的情况下使用php和Curl更改Twitter的状态

通过 CURL 中的 Twitter Rest API 获取多个屏幕名称的最新推文

Spring oauth jwt浏览器在curl失败时工作

Swift Alamofire 上的 Django oauth2 令牌请求失败

TwitteR、ROAuth 和 Windows:注册成功,但证书验证失败

OAuth、PHP、Rest API 和 curl 给出 400 Bad Request