twitter oauth请求令牌失败

时间:2013-10-14 14:32:18

标签: php curl twitter twitter-oauth

我试图实施“用Twitter登录”
我在这里看到了很多关于这个主题的问题,我已经阅读了很多这些问题并且一直坚持下去 我使用了以下链接:

implementing Sign in with Twitter
POST oauth/request_token
Creating a signature
Authorizing a request

,结果是响应:无法验证oauth签名和令牌(可能是最常见的错误=))

我做了什么:

date_default_timezone_set('UTC');
$oauth_consumer_key = 'mYOauThConsuMerKey'; //from app settings

function generate_nonce() {
    $mt = microtime();
    $rand = mt_rand();
    return md5($mt . $rand); // md5s look nicer than numbers
}
$oauth_nonce = generate_nonce();
    $http_method = 'POST';
    $base_url = 'https://api.twitter.com/oauth/request_token';
    $oauth_signature_method = 'HMAC-SHA1';
    $oauth_timestamp = time();
    $oauth_token = 'mytokenFromAPPsettoings';
    $oauth_version = '1.0';
$oauth_callback = 'http://twoends.home/backend';
    $params = array(
        rawurlencode('oauth_nonce')=>rawurlencode($oauth_nonce),
        rawurlencode('oauth_callback')=>rawurlencode($oauth_callback),
        rawurlencode('oauth_signature_method')=>rawurlencode($oauth_signature_method),
        rawurlencode('oauth_timestamp')=>rawurlencode($oauth_timestamp),
        rawurlencode('oauth_token')=>rawurlencode($oauth_token),
        rawurlencode('oauth_version')=>rawurlencode($oauth_version),
    );

    ksort($params);
    $parameter_string = http_build_query($params,'','&');
        $base_string  = strtoupper($http_method).'&';
        $base_string .= rawurlencode($base_url).'&';
        $base_string .= rawurlencode($parameter_string);

        $oauth_consumer_secret = 'myappconsumersecret';
        $oauth_token_secret = 'mytokensecret';
$oauth_signing_key =rawurlencode($oauth_consumer_secret).'&'.rawurlencode($oauth_token_secret);
$oauth_signature = base64_encode(hash_hmac('sha1', $base_string, $oauth_signing_key, true));
$DST ='OAuth ';
foreach($params as $key=>$value){
    $DST .= $key.'='.'"'.$value.'"&';
}
$DST = rtrim($DST,'&');

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $base_url);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: '.$DST));
curl_setopt($ch, CURLINFO_HEADER_OUT, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);

所以,这段代码很挣扎,但仍然会产生错误 在一个主题中,我已经读过在这个阶段不需要令牌:有或没有 - 没有关系 - 仍然是同样的错误 试图玩时间(设置UTC) - 同样的错误
我也尝试使用像this这样的代码,但这对我不起作用 为什么我不使用某人的lib - 因为我想逐步通过算法,但我已经厌倦了它并且需要帮助

事先获得任何帮助,可能会得到一个工作分步指南的例子吗?

3 个答案:

答案 0 :(得分:0)

您的代码似乎有些问题:

1)你的params数组应该包含oauth_consumer_key而不是oauth_token

$params = array(
    rawurlencode('oauth_nonce')=>rawurlencode($oauth_nonce),
    rawurlencode('oauth_callback')=>rawurlencode($oauth_callback),
    rawurlencode('oauth_signature_method')=>rawurlencode($oauth_signature_method),
    rawurlencode('oauth_timestamp')=>rawurlencode($oauth_timestamp),
    rawurlencode('oauth_consumer_key')=>rawurlencode($oauth_consumer_key),
    rawurlencode('oauth_version')=>rawurlencode($oauth_version),
);

2)请求令牌的签名密钥应使用oauth_consumer_secret后跟&符号构建:

  

$ oauth_signing_key = rawurlencode($ oauth_consumer_secret)。'&';

3)您似乎没有在Authorization标头中的任何位置设置签名。做:

$DST ='OAuth ';
foreach($params as $key=>$value){
    $DST .= $key.'='.'"'.$value.'"&';
}
$DST .= 'oauth_signature='.rawurlencode($oauth_signature)

答案 1 :(得分:0)

我想重新审视问题并发布新数据 感谢@Jonny S我发现了一些错误并且又出现了另一个错误=)

所以,我的工作流程现在看起来:

  

生成随机数的函数,附加信息:oauth_nonce in apioauth.net

function generate_nonce() {
    $mt = microtime();
    $rand = mt_rand();

    return md5($mt . $rand); // md5s look nicer than numbers
}
  

Implementing Sign in with Twitter(此链接会向我们显示我们应提前发布的标题),并向我们显示移动方向 - POST oauth/request_token
  此页面链接到oauth docs section 6.1
  在那里我们可以找到请求令牌所需的参数,但在官方文档中你找不到“oauth_calback”参数,它是twitter API中必需的参数!

我要做的下一步 - 收集所需的参数:

  • oauth_consumer_key

    $oauth_consumer_key = 'YoUrS KEy FrOm aPP ApI';
    
  • oauth_nonce

    $oauth_nonce = generate_nonce();
    
  • oauth_callback

    $oauth_callback = 'http://twoends.home/backend';
    
  • oauth_sinature_method

    $oauth_signature_method = 'HMAC-SHA1';
    
  • oauth_timestamp

    $oauth_timestamp = time();
    
  • oauth_version

    $oauth_version = '1.0';
    
  • 其他参数(过程中需要):

  • OAuth签名(最棘手的部分)

此处我们有一个关于如何操作的API页面Creating a signature

首先我们需要收集所有需要的参数,百分比编码和排序,我把它们推到数组:

    $params = array(
        rawurlencode('oauth_consumer_key')=>rawurlencode($oauth_consumer_key),
        rawurlencode('oauth_nonce')=>rawurlencode($oauth_nonce),
        rawurlencode('oauth_callback')=>rawurlencode($oauth_callback),
        rawurlencode('oauth_signature_method')=>rawurlencode($oauth_signature_method),
        rawurlencode('oauth_timestamp')=>rawurlencode($oauth_timestamp),
        rawurlencode('oauth_version')=>rawurlencode($oauth_version),
    );

然后排序:

    ksort($params);

然后我正在创建参数字符串:

    $parameter_string = http_build_query($params,'','&');

结果:

  

PARAM字符串:oauth_callback = HTTP%253A%252F%252Ftwoends.home%252Fbackend&安培; oauth_consumer_key = oauth_consumer_key_wQjQ7u5lgwA&安培; oauth_nonce = 46fa649c21ac5315d4d4510ff68ad630&安培; oauth_signature_method = HMAC-SHA1&安培; oauth_timestamp = 1381930918&安培; oauth_version = 1.0

接下来我需要创建base_string,它将用于创建签名作为hash_hmac()函数的数据参数

    $base_string = strtoupper($http_method).'&';
    $base_string .= rawurlencode($base_url).'&';
    $base_string .= rawurlencode($parameter_string);

结果:

  

POST&安培; HTTPS%3A%2F%2Fapi.twitter.com%2Foauth%2Frequest_token&安培; oauth_callback%3Dhttp%25253A%25252F%25252Ftwoends.home%25252Fbackend%26oauth_consumer_key%3Dapp_cons_keyQjQ7u5lgwA%26oauth_nonce%3D46fa649c21ac5315d4d4510ff68ad630%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp %3D1381930918%26oauth_version%3D1.0

接下来我从APP设置获取consumer_secret以创建签名密钥,该签名密钥将用于在hash_hmac()函数中创建签名作为第三个参数

    $oauth_consumer_secret = 'consumer_secret_from_app_settings';
    $oauth_signing_key = rawurlencode($oauth_consumer_secret).'&';

有一点需要提及:第一步(request_token我们不需要放任何令牌)

此步骤创建签名:

    $oauth_signature = base64_encode(hash_hmac('sha1', $base_string, $oauth_signing_key, true));

现在我们需要为params数组添加签名并构建头字符串

    $params['oauth_signature'] = rawurlencode($oauth_signature);
    ksort($params);

可以在Building the header string

找到构建标题字符串
    $DST ='OAuth ';
    foreach($params as $key=>$value){
        $DST .= $key.'='.'"'.$value.'", ';
    }
    $DST = rtrim($DST,', ');

    //or we can make it by hand as below

    //$DST .= 'oauth_nonce="'.rawurlencode($oauth_nonce)
    //     .'", oauth_callback="'.rawurlencode($oauth_callback)
    //     .'", oauth_signature_method="HMAC-SHA1", oauth_timestamp="'
    //     .rawurlencode($oauth_timestamp).'", oauth_consumer_key="'
    //     .rawurlencode($oauth_consumer_key).'", oauth_signature="'
    //     .rawurlencode($oauth_signature).'", oauth_version="1.0"';

最后一步(我希望)是发送请求:

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $base_url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: '.$DST));
    curl_setopt($ch, CURLINFO_HEADER_OUT, 1);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

    $response = curl_exec($ch);
    $info = curl_getinfo($ch);
    curl_close($ch);

    echo '<pre>';
        print_r($info);
    echo '</pre>';

此代码产生错误400 - 错误请求
如果我删除curl_setopt($ ch,CURLOPT_POST,true);我得到错误 - 401
请求信息转储:

Array
(
    [url] => https://api.twitter.com/oauth/request_token
    [content_type] => 
    [http_code] => 400
    [header_size] => 66
    [request_size] => 471
    [filetime] => -1
    [ssl_verify_result] => 0
    [redirect_count] => 0
    [total_time] => 0.710993
    [namelookup_time] => 0.081279
    [connect_time] => 0.23482
    [pretransfer_time] => 0.550913
    [size_upload] => 0
    [size_download] => 0
    [speed_download] => 0
    [speed_upload] => 0
    [download_content_length] => 0
    [upload_content_length] => -1
    [starttransfer_time] => 0.710976
    [redirect_time] => 0
    [redirect_url] => 
    [primary_ip] => 199.16.156.104
    [certinfo] => Array
    (
    )

    [primary_port] => 443
    [local_ip] => 192.168.1.234
    [local_port] => 54994
    [request_header] => POST /oauth/request_token HTTP/1.1
Host: api.twitter.com
Accept: */*
Authorization: OAuth oauth_callback="http%3A%2F%2Ftwoends.home%2Fbackend", oauth_consumer_key="your_consumer_keyCwQjQ7u5lgwA", oauth_nonce="1ba83f0af239f439c1524096c33faefe", oauth_signature="QZZvrJ8wzCQOYhiKJeT4vz%2FWCcg%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1381931941", oauth_version="1.0"
Content-Length: -1
Content-Type: application/x-www-form-urlencoded
Expect: 100-continue


)

希望这有助于了解在哪里找到错误,提前我还会尝试使用Fiddler跟踪请求

---------------------------------------
通过使用新API解决

答案 2 :(得分:0)

看起来oauth_callback网址在basetring中被三重编码。它应该是以下形式:

POST&https%3A%2F%2Fapi.twitter.com%2Foauth%2Frequest_token&
oauth_callback%3Dhttp%253A%252F%252Ftwoends.home%252Fbackend%26
oauth_consumer_key%3Dapp_cons_keyQjQ7u5lgwA ...

在你的基础字符串中:

oauth_callback%3Dhttp%25253A%25252F%25252Ftwoends.home%25252Fbackend

罪魁祸首似乎是'http_build_query'。