Yahoo API和可怕的oauth_problem =" signature_invalid"

时间:2014-06-09 23:37:49

标签: curl oauth yahoo hmacsha1

我已经在这里阅读了各种其他主题,似乎找不到一个真正给出令人信服的答案。

我一直关注https://developer.yahoo.com/oauth/guide/oauth-accesstoken.html处的文档,现在为我提供了一套很好的凭据和用户ID,无论谁登录。到目前为止,我一直在使用https和明文方法签名。

现在我希望收到有关用户的一些信息,并且必须使用HMACS-SHA1方法签署我的请求。

基本上,像这里的许多其他人一样,我收到了Please提供的有效凭据。 OAuth oauth_problem =" signature_invalid",realm =" yahooapis.com" "错误信息。

这是我的代码:

function getYahooUser($userID, $oauthToken, $oauthSecret)
{
   // $url = 'https://social.yahooapis.com/v1/user/' . $userID .'/profile?';
    $ch = curl_init();

    $s =  'oauth_consumer_key='.config::yahooConsumerKey.'&';
    $s .= 'oauth_nonce='.generateRandomString().'&';
    $s .= 'oauth_signature_method=HMAC-SHA1&';
    $s .= 'oauth_timestamp='.time().'&';
    $s .= 'oauth_token='.$oauthToken.'&';
    $s .= 'oauth_version=1.0&';
    $s .= 'realm=yahooapis.com';

    $baseString ='GET&'.rawurlencode('https://social.yahooapis.com/v1/user/'.$userID.'/profile').'&'.rawurlencode($s);
    $signingKey = rawurlencode(config::yahooConsumerSecret).'&'.rawurlencode($oauthSecret);
    $signature = rawurlencode(base64_encode(hash_hmac('sha1', $baseString, $signingKey, true)));



    curl_setopt_array($ch, array(
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => TRUE,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_SSL_VERIFYHOST => 0,
        CURLOPT_HTTPGET => true,
        CURLOPT_POST       => false,
        CURLOPT_URL => 'https://social.yahooapis.com/v1/user/'.$userID.'/profile'.
            '?realm=yahooapis.com'.
            '&oauth_consumer_key='.config::yahooConsumerKey.
            '&oauth_nonce='.generateRandomString().
            '&oauth_signature_method=HMAC-SHA1'.
            '&oauth_timestamp='.time().
            '&oauth_token='.$oauthToken.
            '&oauth_version=1.0'.
            '&oauth_signature='.$signature
    ));

$output = curl_exec($ch);
    var_dump($output);

    return $output;

}

有没有人知道我做错了什么?

1 个答案:

答案 0 :(得分:2)

说真的,雅虎api令人震惊......

Ok使用https://github.com/joechung/oauth_yahoo提供的Joe Chungs oauth示例和来自雅虎开发者网络https://developer.yahoo.com/forum/OAuth-General-Discussion-YDN-SDKs/token-rejected/1259915145000-8648ab55-f852-38ed-91c9-bf7e37f7d76c

的帖子解决了问题

诀窍是在你的签名创建中添加它之前对你从gettoken请求获得的auth令牌进行url解码。

这是我完整的雅虎功能,如果您遇到同样的问题,那么只需在我的配置中包含您的变量:: params

主要功能:

function doYahoo() //returns a url for the user to click to start auth
{

    require('Yahoo/YahooCurl.php');
    new YahooCurl;
    $yahooReply = getYahooRequestToken();
    $yahooReplyToArray = explode("&", $yahooReply);
    $yahooOauthToken = $yahooReplyToArray[0];
    $yahooOauthToken = substr($yahooOauthToken, 12);

    $yahooOauthTokenSecret = $yahooReplyToArray[1];
    $yahooOauthTokenSecret = substr($yahooOauthTokenSecret,19);


    $expire = time() + 60 * 60 * 24 * 7;
    setcookie("yahooSecret", $yahooOauthTokenSecret, $expire, "/", null);

    $YahooURL = 'https://api.login.yahoo.com/oauth/v2/request_auth?oauth_token=' . $yahooOauthToken;
    return $YahooURL;

}

if(isset($_GET['yahoo']))
{

    $yahoooAuthToken = $_GET['oauth_token'];
    $yahoooAuthVerifier = $_GET['oauth_verifier'];

    require('Yahoo/YahooCurl.php');
    new YahooCurl;

    $yahooReply = getYahooAccessToken($yahoooAuthVerifier, $yahoooAuthToken, $_COOKIE['yahooSecret']);
    $yahooReplyToArray = explode("&", $yahooReply);
    $yahoooAuthToken = $yahooReplyToArray[0];
    $yahoooAuthToken = substr($yahoooAuthToken,12);
    $yahoooAuthToken = urldecode($yahoooAuthToken);
    $yahoooAuthTokenSecret = $yahooReplyToArray[1];
    $yahoooAuthTokenSecret = substr($yahoooAuthTokenSecret,19);
    $YahooUserID = $yahooReplyToArray[5];
    $YahooUserID = substr($YahooUserID,18);
    $YahooRefreshToken = $yahooReplyToArray[3];
    $YahooRefreshToken = substr($YahooRefreshToken,21);

    $expire = time() + 60 * 60 * 24 * 7;
    setcookie("yahooRefresh", $YahooRefreshToken, $expire, "/", null);

    $yahooUserData = getYahooUser($YahooUserID,$yahoooAuthToken,$yahoooAuthTokenSecret);

    //do what you want with $yahooUserData
}

和YahooCurl.php

class YahooCurl
{
    public $YahooRequestToken;
}

function getYahooRequestToken()
{

    $params = array(
        'oauth_nonce' => urlencode(generateRandomString()),
        'oauth_timestamp' => time(),
        'oauth_consumer_key' => config::yahooConsumerKey,
        'oauth_signature_method' => 'plaintext',
        'oauth_signature' => config::yahooConsumerSecret . '%26',
        'oauth_version' => '1.0',
        'oauth_callback' => config::yahooCallBackDomain);

    $url = 'https://api.login.yahoo.com/oauth/v2/get_request_token';
    $postData = '';


    foreach ($params as $k => $v) {
        $postData .= $k . '=' . $v . '&';
    }
    rtrim($postData, '&');

    //var_dump($postData);

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_POST, count($postData));
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);

    $output = curl_exec($ch);
    curl_close($ch);
    return $output;
}

function generateRandomString($length = 6)
{
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, strlen($characters) - 1)];
    }
    return $randomString;
}

function getYahooAccessToken($oauthVerifier, $oauthToken, $oauthSecret)
{

    $url = 'https://api.login.yahoo.com/oauth/v2/get_token?oauth_consumer_key=' .urlencode(config::yahooConsumerKey) .
        '&oauth_signature_method=' . urlencode('plaintext') .
        '&oauth_version=' . urlencode('1.0') .
        '&oauth_verifier=' . urlencode($oauthVerifier) .
        '&oauth_token=' . urlencode($oauthToken) .
        '&oauth_timestamp=' . urlencode(time()) .
        '&oauth_nonce=' .urlencode(generateRandomString()) .
        '&oauth_signature=' . config::yahooConsumerSecret . '%26' . $oauthSecret;

    $ch = curl_init();

    curl_setopt($ch,CURLOPT_URL,$url);
    curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
//  curl_setopt($ch,CURLOPT_HEADER, false);

    $output=curl_exec($ch);

    curl_close($ch);
    return $output;
}

function getYahooUser($userID, $oauthToken, $oauthSecret)
{

    $ch = curl_init();

    $url = 'https://social.yahooapis.com/v1/user/'. $userID . '/profile';
    $params['oauth_consumer_key'] = config::yahooConsumerKey;
    $params['oauth_nonce'] = generateRandomString();
    $params['oauth_signature_method'] = 'HMAC-SHA1';
    $params['oauth_timestamp'] = time();
    $params['oauth_token'] = $oauthToken;
    $params['oauth_version'] = '1.0';
    $params['oauth_signature'] =
        oauth_compute_hmac_sig('GET', $url, $params,
            config::yahooConsumerSecret, $oauthSecret);

    $query_parameter_string = oauth_http_build_query($params);
    $request_url = $url . ($query_parameter_string ?
            ('?' . $query_parameter_string) : '' );


    curl_setopt($ch, CURLOPT_URL, $request_url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);

    $output = curl_exec($ch);
    var_dump($output);

    return $output;

}

    function oauth_compute_hmac_sig($http_method, $url, $params, $consumer_secret, $token_secret)
    {

        $base_string = signature_base_string($http_method, $url, $params);
        $signature_key = rfc3986_encode($consumer_secret) . '&' . rfc3986_encode($token_secret);
        $sig = base64_encode(hash_hmac('sha1', $base_string, $signature_key, true));
        return $sig;
    }

function oauth_http_build_query($params, $excludeOauthParams=false)
{
    $query_string = '';
    if (! empty($params)) {

        // rfc3986 encode both keys and values
        $keys = rfc3986_encode(array_keys($params));
        $values = rfc3986_encode(array_values($params));
        $params = array_combine($keys, $values);

        // Parameters are sorted by name, using lexicographical byte value ordering.
        // http://oauth.net/core/1.0/#rfc.section.9.1.1
        uksort($params, 'strcmp');

        // Turn params array into an array of "key=value" strings
        $kvpairs = array();
        foreach ($params as $k => $v) {
            if ($excludeOauthParams && substr($k, 0, 5) == 'oauth') {
                continue;
            }
            if (is_array($v)) {
                // If two or more parameters share the same name,
                // they are sorted by their value. OAuth Spec: 9.1.1 (1)
                natsort($v);
                foreach ($v as $value_for_same_key) {
                    array_push($kvpairs, ($k . '=' . $value_for_same_key));
                }
            } else {
                // For each parameter, the name is separated from the corresponding
                // value by an '=' character (ASCII code 61). OAuth Spec: 9.1.1 (2)
                array_push($kvpairs, ($k . '=' . $v));
            }
        }

        // Each name-value pair is separated by an '&' character, ASCII code 38.
        // OAuth Spec: 9.1.1 (2)
        $query_string = implode('&', $kvpairs);
    }

    return $query_string;
}

function rfc3986_encode($raw_input)
{
    if (is_array($raw_input)) {
        return array_map('rfc3986_encode', $raw_input);
    } else if (is_scalar($raw_input)) {
        return str_replace('%7E', '~', rawurlencode($raw_input));
    } else {
        return '';
    }
}

function signature_base_string($http_method, $url, $params)
{
    // Decompose and pull query params out of the url
    $query_str = parse_url($url, PHP_URL_QUERY);
    if ($query_str) {
        $parsed_query = oauth_parse_str($query_str);
        // merge params from the url with params array from caller
        $params = array_merge($params, $parsed_query);
    }

    // Remove oauth_signature from params array if present
    if (isset($params['oauth_signature'])) {
        unset($params['oauth_signature']);
    }

    // Create the signature base string. Yes, the $params are double encoded.
    $base_string = rfc3986_encode(strtoupper($http_method)) . '&' .
        rfc3986_encode(normalize_url($url)) . '&' .
        rfc3986_encode(oauth_http_build_query($params));



    return $base_string;
}

function normalize_url($url)
{
    $parts = parse_url($url);

    $scheme = $parts['scheme'];
    $host = $parts['host'];
    $port = '443';
    $path = $parts['path'];

    if (! $port) {
        $port = ($scheme == 'https') ? '443' : '80';
    }
    if (($scheme == 'https' && $port != '443')
        || ($scheme == 'http' && $port != '80')) {
        $host = "$host:$port";
    }

    return "$scheme://$host$path";
}


function oauth_parse_str($query_string)
{
    $query_array = array();

    if (isset($query_string)) {

        // Separate single string into an array of "key=value" strings
        $kvpairs = explode('&', $query_string);

        // Separate each "key=value" string into an array[key] = value
        foreach ($kvpairs as $pair) {
            list($k, $v) = explode('=', $pair, 2);

            // Handle the case where multiple values map to the same key
            // by pulling those values into an array themselves
            if (isset($query_array[$k])) {
                // If the existing value is a scalar, turn it into an array
                if (is_scalar($query_array[$k])) {
                    $query_array[$k] = array($query_array[$k]);
                }
                array_push($query_array[$k], $v);
            } else {
                $query_array[$k] = $v;
            }
        }
    }

    return $query_array;
}

希望这有助于某人。