Google OAuth签名无效响应(PHP)


Google OAuth Signature Invalid response (PHP)

在寻找导致这种情况的原因时,眼睛变得酸痛。我正在缩小范围,但我厌倦了改变不同的参数来让签名通过。我一直在比较我的基本字符串和授权头与那些由谷歌代码操场输出。

我一直在参考这篇文章,并认为我正在接近:

PHP Oauth signature_invalid

基本字符串:

GET& https % % 2 f % 2 3 fwww.google.com % 2 faccounts % 2 foauthgetrequesttoken& oauth_callback % 3 dhttp % % 252 f % 253 252 fgooglecodesamples.com % 252 foauth_playground % 252 findex.php % 26 oauth_consumer_key % 3 danonymous % 26 oauth_nonce % 3 d1f8a27974826a0001f679186898bb79a % 26 oauth_signature_method % 3 dhmac -SHA1 % 26 oauth_timestamp % 3 d1313023952 % 26 oauth_version % 3 d1.0 % 26范围% 3 dhttps % % 252 f % 253 252 fwww.google.com % 252 fcalendar % 252 ffeeds % 252 f

授权标题:

OAuth oauth_consumer_key="anonymous", oauth_nonce="1f8a27974826a0001f679186898bb79a", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1313023952", oauth_callback="http%3A%2F%2Fgooglecodesamples.com%2Foauth_playground%2Findex.php", oauth_version="1.0", oauth_signature="nHL5107wlVXrB5GJjyDClpc5pJs%3D"0signature_invalid

主要功能:

private function oAuthGetRequestToken()
{
    echo "<pre>";
    $secret = 'anonymous';
    $url = 'https://www.google.com/accounts/OAuthGetRequestToken';
    $scope = 'https://www.google.com/calendar/feeds/';
    $authParams = array(
                    'oauth_consumer_key' => 'anonymous',
                    'oauth_nonce' => self::generateNonce(),
                    'oauth_signature_method' => 'HMAC-SHA1',
                    'oauth_timestamp' => time(),
                    'oauth_callback' => 'http://googlecodesamples.com/oauth_playground/index.php',
                    'oauth_version' => '1.0');
    $unsignedBaseString = self::getBaseString('GET', $url, $authParams, $scope);            
    $unsignedKey = array($authParams['oauth_consumer_key'], $secret);
    $unsignedKeyParts = array_map('urlencode', $unsignedKey);
    $key = implode('&', $unsignedKeyParts);
    $oauth_signature = self::hmacsha1($key, $unsignedBaseString);
    $authParams['oauth_signature'] = $oauth_signature;
    $rest = new Rest();
    $oAuthGetRequestTokenResponse = $rest->OAuthHttpGetRequest($url, $authParams, $scope);
    print_r($oAuthGetRequestTokenResponse);
}

辅助功能:

    protected function generateNonce()
{
    $nonce = hash('md5', self::makeRandomString());
    return $nonce;
}
protected function makeRandomString($bits = 256)
{
    $bytes = ceil($bits / 8);
    $return = '';
    for ($i = 0; $i < $bytes; $i++) {
        $return .= chr(mt_rand(0, 255));
    }
    return $return;
}
protected function hmacsha1($key, $data) 
{
    return base64_encode(hash_hmac('sha1', $data, $key, true));
}
protected function getBaseString($method, $url, $authParams, $scope)
{
    $authString = '';       
    foreach($authParams as $key => $value)
        $authString .= $key . "=" . urlencode($value) . "&";
    $authString = rtrim($authString, '&');
    $baseString = $method . '&' . urlencode($scope) . '&' . $authString;
    return $baseString;
}

Rest/请求功能:

public function OAuthHttpGetRequest($url, $authParams, $scope)
{
    $oAuthHeaders = '';
    $oAuthHttpGetResponse;
    foreach($authParams as $key=>$value)
    {
        $oAuthHeaders .= $key . '="' . urlencode($value) . '", ';
    }
    $oAuthHeaders = rtrim($oAuthHeaders, ', ');
    $authString = "OAuth " . $oAuthHeaders;
    echo "<br/>" . $authString;
    $urlWithScope = $url . '?scope=' . urlencode($scope);
    if($curlHandle = curl_init())
    {
        curl_setopt($curlHandle, CURLOPT_URL, $urlWithScope);
        curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curlHandle, CURLOPT_HTTPHEADER, array("Authorization: " . $authString));
        //curl_setopt($curlHandle, CURLOPT_POST, TRUE);
        //curl_setopt($curlHandle, CURLOPT_POSTFIELDS, );
        curl_setopt($curlHandle, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($curlHandle, CURLOPT_SSL_VERIFYHOST, 0);
        $oAuthHttpGetResponse = curl_exec($curlHandle);
        echo curl_errno($curlHandle);
        echo curl_error($curlHandle);
        curl_close($curlHandle);
    }
    else
        die("Could not instance cURL, is the module enabled?");
    return $oAuthHttpGetResponse;
}

一读我认为你的问题是在getBaseString函数:

$baseString = $method . '&' . urlencode($scope) . '&' . $authString;

我认为你应该在这里使用REQUEST TOKEN ENDPOINT而不是作用域…

作用域需要附加参数,因为通常OAuth协议不指定作用域的存在——它们是更好地调优API访问所需的扩展,但它们不是协议工作所必需的。

当创建基本签名字符串时,包含在$方法之后的URL始终是将要接收请求的URL…

就你而言,我认为应该是:

$baseString = $method . '&' . urlencode($url) . '&' . $authString;

—ADDON—

更清楚:当第一次请求请求令牌时,基本字符串应该包含请求令牌结束的URL…

当以后请求ACCESS令牌时,基本字符串应该包含ACCESS令牌端点的URL

最后,在获得ACCESS令牌后,您正在访问资源(作用域),然后基本字符串应包含资源的URL(在您的示例中称为作用域)…