【问题标题】:Google Oauth 400 error when trying to get auth tokens尝试获取身份验证令牌时出现 Google Oauth 400 错误
【发布时间】:2013-12-04 00:32:05
【问题描述】:

我需要修复 PHP Google 身份验证问题。在收到代码失败并出现 400 错误请求后,我正在尝试交换 Auth 令牌。

在阅读文档并一遍又一遍地研究代码之后,我一生都无法弄清楚。

我的网址有问题吗?

$url =  'https://accounts.google.com/o/oauth2/token?&grant_type=authorization_code&code='.$_GET['code']."&client_id=".G_CLIENT_ID."&client_secret=".G_CLIENT_SECRET."&redirect_uri=".REDIRECT_URI;
$context = stream_context_create(
            array( 'http' => 
                array('method' => 'POST',
                )
            )
        );          

echo "<Br> url to fetch  : ". $url;
echo "<Br> context to fetch  : ". $context;

$response = file_get_contents($url, false, $context);

echo "<Br> fetch response : ". $response;   

代码重用是否会迫使 Google 拒绝我的身份验证令牌检索尝试?

Google 没有返回太多信息并返回 400 错误 - 他们肯定应该提供更多信息吗?

编辑 1

print_r返回的请求头(apache_request_headers()) -->

  Array
      (
      [Accept] => text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
      [Accept-Encoding] => gzip,deflate,sdch
      [Accept-Language] => en-US,en;q=0.8
      [Connection] => keep-alive
      [Cookie] => PHPSESSID=ec0b5ff920282245f7ce6d194ba36bd1; _ga=GA1.2.1973782149.1384923620
      [Host] => lxxxxxxr.com
      [User-Agent] => Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36
     )

print_r(apache_response_headers()) 返回的响应头 -->

  Array
  (
  [X-Powered-By] => PHP/5.4.20
  [Expires] => Thu, 19 Nov 1981 08:52:00 GMT
  [Cache-Control] => no-store, no-cache, must-revalidate, post-check=0, pre-check=0
  [Pragma] => no-cache
  [Content-type] => text/html
  )

响应正文 -->

<!DOCTYPE html>
   <html lang=en>
   <meta charset=utf-8>
   <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
   <title>Error 400 (Bad Request)!!1</title>
    <style> ***some style info***    </style>
     <a href=//www.google.com/><img src=//www.google.com/images/errors/logo_sm.gif               alt=Google></a>
     <p><b>400.</b> <ins>That’s an error.</ins>
       <p>Your client has issued a malformed or illegal request.  <ins>That’s all we know.</ins>

编辑 2 - 解决方案:


在比较与我一起工作的 google-api-php-client 示例的输出后,我有一个解决方案。

简单来说,我的网址构造错误。它被构建为一个 GET 查询(尽管他们的文档声称他们想要 POST,但 Linkedin 是如何进行 Oauth 的)

因为这是一个 POST 请求,所以我的 url 应该是

https://accounts.google.com/o/oauth2/token

然后我需要将查询参数作为内容标题的一部分。所以主要工作代码sn-p是

$params = array('code' => $_GET['code'],
        'grant_type' => 'authorization_code',
                'redirect_uri' => 'http://carrotleads.com/',
                'client_id' => G_CLIENT_ID,
                'client_secret' => G_CLIENT_SECRET,
                );  
$url = 'https://accounts.google.com/o/oauth2/token';
$postBody = http_build_query($params);
$requestHttpContext["content"] = $postBody;
$requestHttpContext["method"] = 'POST';

$options = array( 'http' => $requestHttpContext );
$context = stream_context_create( $options );       

echo '<Br>Your request: <pre>'. print_r($url, true) . '</pre>';  
echo '<Br>Your options: <pre>'. print_r( $options, true) . '</pre>';

$response = file_get_contents($url, false, $context);

echo 'Your response_data: <pre>'. print_r($response, true) . '</pre>';

其他信息

Google 的库设置了更多的标头(来自 Google_HttpStreamIO.php)。重要的代码 sn-ps 释义:)

$DEFAULT_HTTP_CONTEXT = array(
 "follow_location" => 0,
 "ignore_errors" => 1,
);
$DEFAULT_SSL_CONTEXT = array(
 "verify_peer" => true,
);
$default_options = stream_context_get_options(stream_context_get_default());
$requestHttpContext = array_key_exists('http', $default_options) ?
    $default_options['http'] : array();

$url = 'https://accounts.google.com/o/oauth2/token';
$params = array('code' => $_GET['code'],
        'grant_type' => 'authorization_code',
                'redirect_uri' => 'http://carrotleads.com/xxxxxxxxxx',
                'client_id' => G_CLIENT_ID,
                'client_secret' => G_CLIENT_SECRET,
                );  
$postBody = http_build_query($params);
$postsLength = strlen($postBody);
$requestHeaders = array_merge( array('content-type' => 'application/x-www-form-urlencoded'), array('content-length' => $postsLength));
$headers = "";
foreach($requestHeaders as $k => $v) {
   $headers .= "$k: $v\n";
}
$requestHttpContext["header"] = $headers;
$requestHttpContext["content"] = $postBody;
$requestHttpContext["method"] = 'POST';

$requestSslContext = array_key_exists('ssl', $default_options) ?
    $default_options['ssl'] : array();

if (!array_key_exists("cafile", $requestSslContext)) {
  $requestSslContext["cafile"] = dirname(__FILE__) . '/cacerts.pem';
}
$options = array("http" => array_merge(self::$DEFAULT_HTTP_CONTEXT,
                                             $requestHttpContext),
                 "ssl" => array_merge(self::$DEFAULT_SSL_CONTEXT,
                                      $requestSslContext));

$context = stream_context_create($options);
$response_data = file_get_contents($url,
                                   false,
                                   $context);

所有这些额外的标头都不需要交换 Auth 令牌,但如果您想按照标准进行,那就是要走的路,包括通过证书文件发送。

如果您需要大量往返 Google API 请求,您最好使用编写良好的 Google 库,否则可能会有点矫枉过正,上面的代码 sn-ps 应该会有所帮助。

事后看来,我觉得很愚蠢,因为我没有发现 POST 与 GET 请求的区别,生活和学习;经过2天的仔细研究,我松了一口气。

【问题讨论】:

  • 粘贴http请求和响应。
  • 所以“您的客户发出了格式错误或非法的请求。”。抱歉,我很讨厌阅读其他人的代码。您可以通过转储实际的 http 请求(因此您可以查看参数的正确 URI 编码之类的内容)并将其与 Oauth Playground 中的等效请求进行比较来自己弄清楚。这就是我在开发过程中出售所有与 oauth 相关的问题的方式。
  • 好吧,我做了所有这些,包括对参数进行 urlencode,将参数与 OAuth 操场进行了比较,但这些都没有帮助。看起来我错过了其他没有记录的东西。

标签: php google-oauth


【解决方案1】:

当您向 Google 发出/o/oauth2/token 的请求时,这必须是 POST。仅将方法更改为 POST 是不够的,您还需要从查询字符串中删除内容,而是实际放入请求的正文中。

我强烈建议您使用 Google 提供的 PHP 库 (https://code.google.com/p/google-api-php-client/),它会为您解决这个问题。

如果您确实需要手动执行此操作,请尝试:

  1. 从“?”中删除所有内容从查询字符串开始。
  2. 创建自己的正文,确保对每个值进行 URL 编码:"grant_type=" . urlencode($_GET['code']) . (etc..)
  3. 包含Content-Type: application/x-www-form-urlencoded 标头和Content-Length: nnn 标头(如果PHP 不自动执行后者。
  4. 是的,可以肯定的是,每个授权码只能使用一次,而且它们的生命周期很短。

【讨论】:

  • 谢谢伙计。使用 google lib 有效,但我不知道为什么,我现在正在深入研究它的代码库以找出原因。一旦我弄清楚就会在这里更新。我已经完成了参数等的 url 编码,但这些都没有帮助。没有尝试内容类型标题,但正在重用我在 Oauth 技术中的链接并且它工作正常,所以从不认为这可能是一个问题。也会试试这个。因此,我认为谷歌应该返回更好的错误,而不仅仅是盲目的错误请求。感谢您的帮助。非常感谢。
【解决方案2】:

这可能是 CURL 请求的问题。在GoogleAnalyticsAPI.class.php &gt; class Http &gt; function curl (around line 720) 中再添加一个选项来阻止 CURL 验证对等方的证书:

curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);

【讨论】:

    【解决方案3】:

    我用这种方式解决了这个问题,当你使用 PHP 版本然后是旧的 5.5.0 时

    <?php
    if(version_compare(PHP_VERSION, '5.5.0', '<')):
        function curl_reset($ch){
            curl_setopt($ch, CURLOPT_HTTPGET, 1);
            curl_setopt($ch, CURLOPT_POST, false);
        }
    endif;
    

    【讨论】:

      猜你喜欢
      • 2015-06-01
      • 2015-04-05
      • 1970-01-01
      • 2020-07-31
      • 2015-05-10
      • 2019-05-07
      • 2016-06-04
      • 2018-02-22
      • 2014-12-24
      相关资源
      最近更新 更多