【问题标题】:Twitter API returns error 215, Bad Authentication DataTwitter API 返回错误 215,错误的身份验证数据
【发布时间】:2012-09-22 23:31:49
【问题描述】:

我正在尝试调用关注 Twitter 的 API 来获取用户的关注者列表。

http://api.twitter.com/1.1/followers/ids.json?cursor=-1&screen_name=username

我收到此错误消息作为响应。

{
    code = 215;
    message = "Bad Authentication data";
}

我似乎找不到与此错误代码相关的文档。有人知道这个错误吗?

【问题讨论】:

  • 我们很多人都在同一条船上。你能解决这个问题吗?我很想看到 1.1 的解决方案,因为 1.0 已被弃用。
  • 不幸的是,我仍然无法找到合适的解决方案。我现在正在开发版本 1。但是当我这样做时,我一定会在这里发布。如果您在此之前得到它,请分享...
  • 有没有人注意到 Twitter oauth 工具生成的 URL 中包含“/1.1”,但 cURL 命令显示“oauth_version=1.0”? dev.twitter.com/apps/XXXXXX/oauth?nid=10364
  • @systemblogger 好吧,OAuth 版本和 twitter API 版本不是一回事。至于 OAuth,有 1.0 和 2.0 atm,我很高兴 Twitter 仍然使用 1.0。
  • 这里首先每个人都需要使用oauth2/token api然后使用followers/list api。否则,您将收到此错误。因为关注者/列表 api 需要身份验证。在 Swift 中点击此链接,stackoverflow.com/questions/12053159/…

标签: php api twitter


【解决方案1】:

非常简洁的代码,没有任何其他 php 文件包括 oauth 等。 请注意,要获得以下密钥,您需要使用https://dev.twitter.com 注册并创建应用程序。

<?php
$token = 'YOUR_TOKEN';
$token_secret = 'YOUR_TOKEN_SECRET';
$consumer_key = 'CONSUMER_KEY';
$consumer_secret = 'CONSUMER_SECRET';

$host = 'api.twitter.com';
$method = 'GET';
$path = '/1.1/statuses/user_timeline.json'; // api call path

$query = array( // query parameters
    'screen_name' => 'twitterapi',
    'count' => '5'
);

$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("&amp;","&",$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);

$twitter_data = json_decode($json);


foreach ($twitter_data as &$value) {
   $tweetout .= preg_replace("/(http:\/\/|(www\.))(([^\s<]{4,68})[^\s<]*)/", '<a href="http://$2$3" target="_blank">$1$2$4</a>', $value->text);
   $tweetout = preg_replace("/@(\w+)/", "<a href=\"http://www.twitter.com/\\1\" target=\"_blank\">@\\1</a>", $tweetout);
   $tweetout = preg_replace("/#(\w+)/", "<a href=\"http://search.twitter.com/search?q=\\1\" target=\"_blank\">#\\1</a>", $tweetout);
}

echo $tweetout;

?>

问候

【讨论】:

  • 这是因为“CURLOPT_SSL_VERIFYPEER = false”。我们查明是cURL SSL证书验证错误,导致Twitter库总是返回空响应。
【解决方案2】:

目前我找到的唯一解决方案是:

  • 在 twitter 开发者面板中创建应用程序
  • 使用您的应用程序(或您在用户帐户中的应用程序)授权用户并保存 Twitter 给您的“oauth_token”和“oauth_token_secret”。为此使用 TwitterOAuth 库,这很简单,请参阅库附带的示例。
  • 使用此令牌,您可以代表用户发出经过身份验证的请求。你可以用同一个库来做。

    // Arguments 1 and 2 - your application static tokens, 2 and 3 - user tokens, received from Twitter during authentification  
    $connection = new TwitterOAuth(TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET, $tokens['oauth_token'], $tokens['oauth_token_secret']);  
    $connection->host = 'https://api.twitter.com/1.1/'; // By default library uses API version 1.  
    $friendsJson = $connection->get('/friends/ids.json?cursor=-1&user_id=34342323');  
    

这将返回用户的朋友列表。

【讨论】:

    【解决方案3】:

    找到解决方案 - 使用 Abraham TwitterOAuth library。如果您使用的是较旧的实现,则应在实例化新的 TwitterOAuth 对象后添加以下行:

    $connection->host = "https://api.twitter.com/1.1/";
    $connection->ssl_verifypeer = TRUE;
    $connection->content_type = 'application/x-www-form-urlencoded';
    

    前 2 行现在记录在 Abraham 库自述文件中,但第 3 行没有。还要确保您的 oauth_version 仍然是 1.0。

    这是我的代码,用于使用新认证的用户从“u​​sers/show”获取所有用户数据,并使用 1.1 返回用户全名和用户图标 - 以下代码在身份验证回调文件中实现:

    session_start();
    require ('twitteroauth/twitteroauth.php');
    require ('twitteroauth/config.php');
    
    $consumer_key = '****************';
    $consumer_secret = '**********************************';
    
    $to = new TwitterOAuth($consumer_key, $consumer_secret);
    
    $tok = $to->getRequestToken('http://exampleredirect.com?twitoa=1');
    
    $token = $tok['oauth_token'];
    $secret = $tok['oauth_token_secret'];
    
    //save tokens to session
    $_SESSION['ttok'] = $token;
    $_SESSION['tsec'] = $secret;
    
    $request_link = $to->getAuthorizeURL($token,TRUE);
    
    header('Location: ' . $request_link);
    

    下面的代码在身份验证和令牌请求之后的重定向中

    if($_REQUEST['twitoa']==1){
        require ('twitteroauth/twitteroauth.php');
        require_once('twitteroauth/config.php');
        //Twitter Creds
        $consumer_key = '*****************';
        $consumer_secret = '************************************';
    
        $oauth_token = $_GET['oauth_token']; //ex Request vals->http://domain.com/twitter_callback.php?oauth_token=MQZFhVRAP6jjsJdTunRYPXoPFzsXXKK0mQS3SxhNXZI&oauth_verifier=A5tYHnAsbxf3DBinZ1dZEj0hPgVdQ6vvjBJYg5UdJI
    
        $ttok = $_SESSION['ttok'];
        $tsec = $_SESSION['tsec'];
    
        $to = new TwitterOAuth($consumer_key, $consumer_secret, $ttok, $tsec);
        $tok = $to->getAccessToken();
        $btok = $tok['oauth_token'];
        $bsec = $tok['oauth_token_secret'];
        $twit_u_id = $tok['user_id'];
        $twit_screen_name = $tok['screen_name'];
    
        //Twitter 1.1 DEBUG
        //print_r($tok);
        //echo '<br/><br/>';
        //print_r($to);
        //echo '<br/><br/>';
        //echo $btok . '<br/><br/>';
        //echo $bsec . '<br/><br/>';
        //echo $twit_u_id . '<br/><br/>';
        //echo $twit_screen_name . '<br/><br/>';
    
        $twit_screen_name=urlencode($twit_screen_name);
        $connection = new TwitterOAuth($consumer_key, $consumer_secret, $btok, $bsec);
        $connection->host = "https://api.twitter.com/1.1/";
        $connection->ssl_verifypeer = TRUE;
        $connection->content_type = 'application/x-www-form-urlencoded';
        $ucontent = $connection->get('users/show', array('screen_name' => $twit_screen_name));
    
        //echo 'connection:<br/><br/>';
        //print_r($connection);
        //echo '<br/><br/>';
        //print_r($ucontent);
    
        $t_user_name = $ucontent->name;
        $t_user_icon = $ucontent->profile_image_url;
    
        //echo $t_user_name.'<br/><br/>';
        //echo $t_user_icon.'<br/><br/>';
    }
    

    我花了太长时间才弄清楚这一点。希望这对某人有帮助!

    【讨论】:

      【解决方案4】:

      Gruik 的回答在下面的帖子中对我有用。

      {摘录 | Zend_Service_Twitter - Make API v1.1 ready}

      对于 ZF 1.12.3,解决方法是在 oauthOptions 选项中传递 consumerKey 和 consumerSecret,而不是直接在选项中。

          $options = array(
              'username' => /*...*/,
              'accessToken' => /*...*/,
              'oauthOptions' => array(
                  'consumerKey' => /*...*/,
                  'consumerSecret' => /*...*/,
              )
          );
      

      【讨论】:

        【解决方案5】:

        更新: Twitter API 1 现已弃用。参考上面的答案。

        Twitter 1.1 不适用于该语法(当我写这个答案时)。必须是 1,而不是 1.1。这将起作用:

        http://api.twitter.com/1/followers/ids.json?cursor=-1&screen_name=username

        【讨论】:

        • 是的,没错。但那是因为 Twitter 的文档建议我这样做。 (dev.twitter.com/docs/api/1/get/followers/ids)。他们说版本 1 已弃用,我需要迁移到 1.1。版本 1 肯定适用于此 Web 服务。但我很困惑为什么 1.1 不适合我?
        • 版本 1 将从 2013 年 3 月算起的 6 个月内被弃用,所以我会选择版本 1.1
        • 测试我坚持使用 Twitter Async 的不同 OAuth 库,只需在文件 EpiTwitter.php 中更改这一行 protected $apiVersion = '1.1'; 即可适用于 Twitter API 1.1 版
        • Twitter API 1 已弃用
        • Twitter REST API v1 不再有效。请迁移到 API v1.1。 dev.twitter.com/docs/api/1.1/overview.
        【解决方案6】:

        /1.1/的url是正确的,是新的Twitter API Version 1.1。

        但您需要一个应用程序并使用 oAuth 授权您的应用程序(和用户)。

        Twitter Developers documentation site 上了解更多信息 :)

        【讨论】:

        • 引用文档站点并不能真正回答问题。
        • @moluv00 OP 说:“我似乎找不到与此错误代码相关的文档。”
        • 你为什么要发布一个通用链接。这不是答案。
        【解决方案7】:

        您需要将 customerKeycustomerSecret 发送到 Zend_Service_Twitter

        $twitter = new Zend_Service_Twitter(array(
                        'consumerKey' => $this->consumer_key,
                        'consumerSecret' => $this->consumer_secret,
                        'username' => $user->screenName,
                        'accessToken' => unserialize($user->token)
        ));
        

        【讨论】:

          【解决方案8】:

          经过两天的研究,我终于发现可以访问 s.o.公共推文您只需要任何应用程序凭据,而不是特定用户的凭据。因此,如果您正在为客户开发,您不必要求他们做任何事情。

          要使用新的 Twitter API 1.1,您需要做两件事:

          首先,您可以(实际上必须)使用您自己的凭据创建应用程序,然后获取访问令牌 (OAUTH_TOKEN) 和访问令牌密钥 (OAUTH_TOKEN_SECRET) 来自“您的访问令牌”部分。 然后在新 TwitterOAuth 对象的构造函数中提供它们。现在您可以访问任何人公开推文。

          $connection = new TwitterOAuth( CONSUMER_KEY, CONSUMER_SECRET, OAUTH_TOKEN, OAUTH_TOKEN_SECRET );
          
          $connection->host = "https://api.twitter.com/1.1/"; // change the default
          $connection->ssl_verifypeer = TRUE;
          $connection->content_type = 'application/x-www-form-urlencoded';
          
          $tweets = $connection->get('http://api.twitter.com/1.1/statuses/user_timeline.json?screen_name='.$username.'&count='.$count);
          

          其实我觉得这也是Pavel 所建议的,但从他的回答中就不是那么明显了。

          希望这两天可以节省其他人:)

          【讨论】:

            【解决方案9】:

            这可能有助于使用 Zend_Oauth_Client 的人使用 twitter api。这个工作配置:

            $accessToken = new Zend_Oauth_Token_Access();
            $accessToken->setToken('accessToken');
            $accessToken->setTokenSecret('accessTokenSecret');
            
            $client = $accessToken->getHttpClient(array(
                'requestScheme' => Zend_Oauth::REQUEST_SCHEME_HEADER,
                'version' => '1.0', // it was 1.1 and I got 215 error.
                'signatureMethod' => 'HMAC-SHA1',
                'consumerKey' => 'foo',
                'consumerSecret' => 'bar',
                'requestTokenUrl' => 'https://api.twitter.com/oauth/request_token',
                'authorizeUrl' => 'https://api.twitter.com/oauth/authorize',
                'accessTokenUrl' => 'https://api.twitter.com/oauth/access_token',
                'timeout' => 30
            ));
            

            看起来 twitter api 1.0 允许 oauth 版本为 1.1 和 1.0,而 twitter api 1.1 只要求 oauth 版本为 1.0。

            P.S 我们不使用 Zend_Service_Twitter,因为它不允许在状态更新时发送自定义参数。

            【讨论】:

              【解决方案10】:

              确保您对 twitter 中的应用程序具有读写权限

              【讨论】:

                【解决方案11】:

                我正在使用HybridAuth 并在连接到 Twitter 时遇到此错误。我追踪到(我)向 Twitter 发送错误大小写的请求类型(get/post 而不是 GET/POST)。

                这将导致 215:

                $call = '/search/tweets.json';
                $call_type = 'get';
                $call_args = array(
                    'q'           => 'pancakes',
                    'count'       => 5,
                );
                $response = $provider_api->api( $call, $call_type, $call_args );
                

                这不会:

                $call = '/search/tweets.json';
                $call_type = 'GET';
                $call_args = array(
                    'q'           => 'pancakes',
                    'count'       => 5,
                );
                $response = $provider_api->api( $call, $call_type, $call_args );
                

                旁注:在 HybridAuth 的情况下,以下内容也不会(因为 HA 在内部为请求类型提供了正确大小写的值):

                $call = '/search/tweets.json';
                $call_args = array(
                    'q'           => 'pancakes',
                    'count'       => 5,
                );
                $response = $providers['Twitter']->get( $call, $call_args );
                

                【讨论】:

                  【解决方案12】:

                  我一直面临同样的问题,我想出的唯一解决方案是直接在新的 TwitterOAuth 类定义中输入 CONSUMER_KEYCONSUMER_SECRET

                  $connection = new TwitterOAuth(  "MY_CK" , "MY_CS"  );
                  

                  不要对此使用变量或静态变量,看看问题是否已解决。

                  【讨论】:

                    【解决方案13】:

                    这里首先每个人都需要使用oauth2/token api,然后使用followers/list api
                    否则,您将收到此错误。因为关注者/列表 api 需要身份验证。

                    在 swift(对于移动应用程序)中,我也遇到了同样的问题。

                    如果你想知道 api 和它的参数,请点击这个链接,Get twitter friends list in swift?

                    【讨论】:

                      【解决方案14】:

                      我知道这是旧的,但昨天我在使用 C# 和带有承载身份验证令牌的 HttpClient 类调用此 URL 时遇到了同样的问题:

                      http://api.twitter.com/1.1/followers/ids.json?cursor=-1&screen_name=username

                      事实证明,我的解决方案是使用 HTTPS 而不是 HTTP。所以我的网址看起来像这样:

                      https://api.twitter.com/1.1/followers/ids.json?cursor=-1&screen_name=username

                      所以这是我的代码的 sn-p:

                                  using (var client = new HttpClient())
                                  {
                                      client.BaseAddress = new Uri("https://api.twitter.com/1.1/");
                                      client.DefaultRequestHeaders.Accept.Clear();
                                      client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                                      client.DefaultRequestHeaders.Add("Authorization", "Bearer **** YOUR BEARER TOKEN GOES HERE ****");
                      
                                      var response = client.GetAsync("statuses/user_timeline.json?count=10&screen_name=username").Result;
                                      if (!response.IsSuccessStatusCode)
                                      {
                                          return result;
                                      }
                                      var items = response.Content.ReadAsAsync<IEnumerable<dynamic>>().Result;
                                      foreach (dynamic item in items)
                                      {
                                          //Do the needful
                                      }
                                  }
                      

                      【讨论】:

                      【解决方案15】:

                      试试这个推特API explorer,你可以作为开发者登录并查询任何你想要的。

                      【讨论】:

                        猜你喜欢
                        • 2013-10-05
                        • 2019-07-24
                        • 2015-07-10
                        • 2020-11-05
                        • 1970-01-01
                        • 2013-06-30
                        • 2013-01-02
                        • 1970-01-01
                        • 2012-11-24
                        相关资源
                        最近更新 更多