Google OAuth签名无效响应(PHP)

Google OAuth签名无效响应(PHP),php,oauth,signature,Php,Oauth,Signature,为了找出导致这种情况的原因,眼睛越来越痛。我正在缩小它的范围,但是我已经厌倦了改变不同的参数来让签名通过。我一直在将我的基本字符串和授权头与google代码平台的输出进行比较 我一直在引用这篇文章,并认为我正在接近: 我的基本字符串: 获取和https%3A%2F%2Fwww.google.com%2fcaccounts%2fauthGetRequestToken&oauth\u回调%3Dhttp%253A%252F%252Fgooglecodesamples.com%252Foauth\u游乐

为了找出导致这种情况的原因,眼睛越来越痛。我正在缩小它的范围,但是我已经厌倦了改变不同的参数来让签名通过。我一直在将我的基本字符串和授权头与google代码平台的输出进行比较

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

我的基本字符串:

获取和https%3A%2F%2Fwww.google.com%2fcaccounts%2fauthGetRequestToken&oauth\u回调%3Dhttp%253A%252F%252Fgooglecodesamples.com%252Foauth\u游乐场%252Findex.php%26oauth\u消费者密钥%3Danonymous%26oauth\u nonce%3D1f8a27974826a0001f679186898bb79a%26oauth\u签名\u方法%3DHMAC- SHA1%26oauth_时间戳%3D1313023952%26oauth_版本%3D1.0%26scope%3Dhttps%253A%252F%252Fwww.google.com%252Fcalendar%252Ffeeds%252F

授权标头:

OAuth OAuth_consumer key=“匿名”,OAuth_nonce=“1f8a27974826a0001f679186898bb79a”,OAuth_signature\u method=“HMAC-SHA1”,OAuth_timestamp=“1313023952”,OAuth_callback=“http%3A%2F%2Fgooglecodesamples.com%2fauth\u playerd%2finder.php”,OAuth_version=“1.0”,OAuth_signature=“NHL5107WLVxRB5GJYDCLPC5PcJS%3D”0signature\u无效

主要功能:

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);
}
专用函数oAuthGetRequestToken()
{
回声“;
$secret='anonymous';
$url='1https://www.google.com/accounts/OAuthGetRequestToken';
$scope='1https://www.google.com/calendar/feeds/';
$authParams=数组(
'oauth_consumer_key'=>'anonymous',
'oauth_nonce'=>self::generateOnce(),
“oauth_签名_方法”=>“HMAC-SHA1”,
'oauth_timestamp'=>time(),
“oauth_回调”=>”http://googlecodesamples.com/oauth_playground/index.php',
“oauth_版本”=>“1.0”);
$unsignedBaseString=self::getBaseString('GET',$url,$authParams,$scope);
$unsignedKey=array($authParams['oauth\u consumer\u key',$secret);
$unsignedKeyParts=数组映射('urlencode',$unsignedKey);
$key=内爆(“&”,$unsignedKeyParts);
$oauth_signature=self::hmacsha1($key,$unsignedBaseString);
$authParams['oauth_签名]=$oauth_签名;
$rest=新的rest();
$oAuthGetRequestTokenResponse=$rest->OAuthHttpGetRequest($url、$authParams、$scope);
打印(oAuthGetRequestTokenResponse);
}
助手功能:

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;
}
受保护的函数generateOnce()
{
$nonce=hash('md5',self::makeRandomString());
返回$nonce;
}
受保护函数makeRandomString($bit=256)
{
$bytes=ceil($bits/8);
$return='';
对于($i=0;$i<$bytes;$i++){
$return.=chr(mt_rand(0255));
}
return$return;
}
受保护函数hmacsha1($key,$data)
{
返回base64_encode(hash_hmac('sha1',$data,$key,true));
}
受保护的函数getBaseString($method、$url、$authParams、$scope)
{
$authString='';
foreach($authParams作为$key=>$value)
$authString.=$key.='.urlencode($value)。“&”;
$authString=rtrim($authString,&');
$baseString=$method'.&'.urlencode($scope)。'&'.$authString;
返回$baseString;
}
休息/请求功能:

$baseString = $method . '&' . urlencode($scope) . '&' . $authString;
$baseString = $method . '&' . urlencode($url) . '&' . $authString;
公共函数OAuthHttpGetRequest($url、$authParams、$scope) { $oAuthHeaders=''; $oAuthHttpGetResponse; foreach($authParams作为$key=>$value) { $oAuthHeaders.=$key.'=''。urlencode($value)。'','; } $oAuthHeaders=rtrim($oAuthHeaders,,'); $authString=“OAuth”。$oAuthHeaders; 回显“
.”$authString; $urlWithScope=$url'.?scope='.urlencode($scope); 如果($curlHandle=curl\u init()) { curl_setopt($curlHandle,CURLOPT_URL,$urlWithScope); curl_setopt($curlHandle,CURLOPT_RETURNTRANSFER,1); curl_setopt($curlHandle,CURLOPT_HTTPHEADER,数组(“授权:”.$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\u exec($curlHandle); echo curl_errno($curlHandle); echo curl_错误($curlHandle); 卷曲关闭($curlHandle); } 其他的 die(“无法实例cURL,模块是否已启用?”); 返回$oAuthHttpGetResponse; }
第一次阅读时,我认为您的问题在于getBaseString函数:

$baseString = $method . '&' . urlencode($scope) . '&' . $authString;
$baseString = $method . '&' . urlencode($url) . '&' . $authString;
我认为您应该在这里使用请求令牌端点,而不是范围

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

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

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

---插件---

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

稍后请求访问令牌时,基本字符串应包含访问令牌端点的URL


最后,在获得访问令牌后,您正在访问一个资源(作用域),那么基本字符串应该包含该资源的URL(在您的示例中称为作用域).

Hi,我不确定我是否理解这一点。我正在尝试为Gmail和Google+获取身份验证令牌。查看文档(at)意味着(至少对我来说)在同一个请求中可以有多个作用域。我的请求令牌的作用域现在是“scope=http%3A%2F%2Fmail.google.com%2Fmail%2Ffeed%2faom%2F+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email”,但这将返回http/1.1400错误请求GSE签名\u无效。一切都是通过Gmail认证的。当我尝试添加G+范围时,它会中断。有什么想法吗?