Google OAuth 签名无效响应 (PHP)
试图找出导致此问题的问题时,眼睛变得酸痛。我正在缩小范围,但我厌倦了更改不同的参数来让签名通过。我一直在将我的基本字符串和授权标头与 google-code-playground 的输出进行比较。
我一直在引用这篇文章,并认为我已经接近了:
PHP Oauthsignature_invalid
我的基本字符串:
GET&https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthGetRequestToken&oauth_callback%3Dhttp%253A%252F%252Fgooglecodesamples.com%252Foaut h_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
授权标头:
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;
}
休息/请求功能:
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;
}
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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
第一次阅读时,我认为您的问题出在 getBaseString 函数中:
我认为您应该在此处使用 REQUEST TOKEN ENDPOINT 而不是范围...
范围是通过附加参数请求的,因为通常 OAuth 协议不指定范围的存在- 它们是更好地调整 API 访问所需的扩展,但它们并不是协议正常工作所必需的。
创建基本签名字符串时,$method 之后包含的 URL 始终是要接收请求的 URL...
在您的情况下,我认为它应该是:
--- ADDON ---
To be更清楚:当第一次请求 REQUEST 令牌时,基本字符串应包含 REQUET TOKEN 端点的 URL...
当稍后请求 ACCESS 令牌时,基本字符串应包含 ACCESS TOKEN 端点的 URL
最后,在获得 ACCESS 令牌后,您是访问资源(范围),那么基本字符串应包含资源的 URL(在您的示例中也称为范围)...
on first read I think your problem is in the getBaseString function:
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:
--- 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)...