OAuth 2.0对于服务器端Web应用程序不起作用

3
我正在尝试使用Google联系人API获取Gmail联系人。为此,我使用了OAuth 2.0。我在这里阅读了他们关于使用OAuth 2.0的指南,并广泛地遵循了以下步骤:
  1. 使用Google注册我的应用程序并获取客户端ID和客户端密钥,然后将我的重定向URI注册到其中。
  2. 现在,我首先创建了一个名为sample.php的文件,如果用户点击“获取联系人”,则会重定向到Google确认页面。
  3. 现在,Google要求进行确认,如果用户同意提供其联系人详细信息,则会将其重定向到带有代码的重定向URI。
  4. 现在,我提取代码并发出POST请求以获取OAuth令牌,如果我获得令牌,则会请求联系人。
sample.php的代码如下:
<?php
$client_id="my client id";
$redirect_uri="http://localhost/htdocs/contacts/redirect.php";
echo <<<doc
<html>
<body>
<a href="http://accounts.google.com/o/oauth2/auth?client_id=$client_id&redirect_uri=$redirect_uri&scope=https://www.google.com/m8/feeds/&response_type=code">
get contacts
</a>
doc;
echo <<<doc
</body>
</html>
doc;
?>

redirect.php 的代码如下所示:

<?php
$client_id="my client id";
$client_sec="my client secret ";  
$redirect_uri="http://localhost/htdocs/contacts/redirect.php";
$code=$_GET['code'];
$post="code=$code&client_id=$client_id&client_secret=$client_sec&redirect_uri=$redirect_uri&grant_type=authorization_code";
$post=urlencode($post);
 //the following curl request is made to get the authorization token
$ch=curl_init();
$url="https://accounts.google.com/o/oauth2/token";
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);
curl_setopt($ch,CURLOPT_AUTOREFERER,1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch,CURLOPT_POST,1);
curl_setopt($ch,CURLOPT_POSTFIELDS,$post);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
$json=curl_exec($ch);
curl_close($ch);
echo $json;     // this is showing Required parameter is missing: grant_type Error 400
$res=json_decode($json,true);
print_r($res);   // this is just for debugging
$token=$res['access_token'];
echo $token;   // this is just for debugging
$url="https://www.google.com/m8/feeds/contacts/default/full?oauth_token=$token";
  //the following curl request is made to get the contacts
$ch=curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);
curl_setopt($ch,CURLOPT_AUTOREFERER,1);
$xml=curl_exec($ch);
echo $xml;
curl_close($ch);
$dom= new DOMDocument();
$dom->loadXML($xml);
$xpath=new DOMXPath($dom);
$path='//gd:email';
$nodes=$xpath->query($path);
echo $nodes->length."<br />";
foreach($nodes as $node)
{
$email=$node->attributes->getNamedItem('address')->nodeValue;
echo $email."<br />";
}
?>

现在的问题是第四步失败了。它一直进行到确认步骤,但当我点击“允许访问”时,我被重定向到我的“重定向URI”,但它显示“必需参数缺失:grant_type 错误400”。
现在我不明白这是为什么,因为我提供了“grant_type”参数。我查看了“firebug”,发现正在进行一个POST请求,但不是我想要的那个。正在进行的POST请求是:
https://accounts.google.com/o/oauth2/approval?xsrfsign=AC9jObYAAAAATkfm3uvx0sfsW7WVmB_FeRqVPLjDcTLz,状态显示为“302暂时移动”。我不明白发生了什么。他们在“OAuth工作流程”中改变了什么吗?需要一些帮助。
编辑:根据Ikke的建议,我去掉了“grant_type”前面的空格,然后它就起作用了。现在我可以获取访问令牌,但仍然无法获取联系人(我会收到一个错误,如“htdocs\contacts\redirect.php的第35行输入为空字符串”),因此似乎没有进行GET请求。此外,我也无法在“firebug”中看到正在进行的POST请求(但肯定正在进行,因为我得到了访问令牌作为响应)。我也看不到我在POST请求之后进行的GET请求,出了什么问题?
更新:问题是请求使用https,并且我没有使用适当的https标头。我使用了正确的标头,它起作用了。问题解决了吗?也许吧。因为我仍然不明白为什么无法在“firebug”的“net”选项卡中看到那些GET和POST请求。

1
可能是打错了,但在 & 和 grant_type 之间有一个空格。 - Ikke
@Ikke 谢谢,那个方法有效。现在我能够获取“访问令牌”,但还没有获取联系人。让我看看是否也能获取联系人。请将其作为答案发布,我会标记为已接受。再次感谢。 - lovesh
“无法获取联系人”是什么意思? - Ikke
@ikke 我的意思是我没有得到联系人页面。我没有看到针对联系人的curl get请求被执行。我收到了一条消息,内容为“在C:\xampp\htdocs\contacts\redirect.php的第35行提供了空字符串作为输入”,第35行指的是“$dom->loadXML($xml);”。 - lovesh
3个回答

2

grant_type&之间需要有一个空格。没有这个空格可能会导致谷歌无法识别该参数。


谢谢。请看我问题中的编辑。我对firebug中的某些东西感到困惑。 - lovesh

1

因为我仍然不明白为什么我无法在Firebug的“net”选项卡中看到那些GET和POST请求。

我假设由于您正在使用curl请求内容,这与Firefox无关,因为curl是一个服务器端库,因此由curl发出的POST请求不会通过浏览器进行,因此Firebug无法看到它们。


0

您正在将已经进行了 URL 编码的字符串传递给 PHP 的 urlencode() 函数:

$post="code=$code&client_id=$client_id&client_secret=$client_sec&redirect_uri=$redirect_uri&grant_type=authorization_code";
$post=urlencode($post);

这会破坏数值,Google的服务器无法正确解析,因此报告缺少参数。删除$post=urlencode($post);这一行,看看是否能够更好地工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接