dongrong1856 2011-08-11 00:56
浏览 77

Google OAuth签名无效响应(PHP)

Eyes are getting sore trying to hunt down the issue causing this. I'm narrowing it down but I'm tired of changing different parameters to get the signature to pass. I've been comparing my base string and Authorization headers with those output by the google-code-playground.

I've been referencing this article and think I am getting close:

PHP Oauth signature_invalid

My base string:

GET&https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthGetRequestToken&oauth_callback%3Dhttp%253A%252F%252Fgooglecodesamples.com%252Foauth_playground%252Findex.php%26oauth_consumer_key%3Danonymous%26oauth_nonce%3D1f8a27974826a0001f679186898bb79a%26oauth_signature_method%3DHMAC- SHA1%26oauth_timestamp%3D1313023952%26oauth_version%3D1.0%26scope%3Dhttps%253A%252F%252Fwww.google.com%252Fcalendar%252Ffeeds%252F

Authorization headers:

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

Main Function:

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);
}

Helper functions:

    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/Request function:

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;
}
  • 写回答

1条回答 默认 最新

  • duanhu7400 2011-08-11 08:33
    关注

    on first read I think your problem is in the getBaseString function:

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

    I think that you should use the REQUEST TOKEN ENDPOINT here instead of the scope...

    Scopes are requested with additional parameter, because generally the OAuth protocol does not specify the existence of scopes - they are extension needed to better tune API access, but they are not mandatory for the protocol to work.

    And when creating the base signature string, the URL that is included after the $method, is always the URL which is going to receive the request...

    In your case I think it should be:

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

    --- ADDON ---

    To be more clear: when first requesting REQUEST token, the base string should contain the URL of the REQUET TOKEN endpoing...

    When later requesting ACCESS token, the base string should contain the URL of the ACCESS TOKEN endpoint

    When finally, after getting ACCESS token you are accessing a resource (scope) then the base string should contain the URL of the resource (aka scope in your example)...

    评论

报告相同问题?

悬赏问题

  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料