简体   繁体   English

Google OAuth 签名无效响应 (PHP)

[英]Google OAuth Signature Invalid response (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.我一直在将我的基本字符串和授权标头与 google-code-playground 的 output 进行比较。

I've been referencing this article and think I am getting close:我一直在参考这篇文章,并认为我已经接近了:

PHP Oauth signature_invalidPHP Oauth 签名_无效

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 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 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:主要 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:休息/请求 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;
}

on first read I think your problem is in the getBaseString function:在第一次阅读时,我认为您的问题出在 getBaseString function 中:

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

I think that you should use the REQUEST TOKEN ENDPOINT here instead of the scope...我认为您应该在这里使用 REQUEST TOKEN ENDPOINT 而不是 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.使用附加参数请求范围,因为通常 OAuth 协议不指定范围的存在 - 它们是更好地调整 API 访问所需的扩展,但它们不是协议工作的强制性。

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...在创建基本签名字符串时,包含在 $method 之后的 URL 始终是将接收请求的 URL...

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...更清楚一点:第一次请求 REQUEST 令牌时,基本字符串应包含 REQUET TOKEN 端点的 URL...

When later requesting ACCESS token, the base string should contain the URL of the ACCESS TOKEN endpoint稍后请求 ACCESS 令牌时,基本字符串应包含 ACCESS TOKEN 端点的 URL

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)...最后,在获得 ACCESS 令牌后,您正在访问资源(范围),那么基本字符串应包含资源的 URL(在您的示例中也称为 scope)...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM