【问题标题】:POST using CURL in PHP gives invalid request Error在 PHP 中使用 CURL POST 给出无效请求错误
【发布时间】:2012-06-11 13:04:27
【问题描述】:

我正在使用 curl 为谷歌帐户使用以下发布方法,但它给了我 invalid_request 错误。

POST /o/oauth2/token HTTP/1.1
Host: accounts.google.com
Content-Type: application/x-www-form-urlencoded

code=4/ux5gNj-_mIu4DOD_gNZdjX9EtOFf&
client_id=1084945748469-eg34imk572gdhu83gj5p0an9fut6urp5.apps.googleusercontent.com&
client_secret=CENSORED&
redirect_uri=http://localhost/oauth2callback&
grant_type=authorization_code

这是我的带有 curl 的 PHP 代码

$text ='test';

$URL = "https://accounts.google.com/o/oauth2/token";

$header = array(
"POST /o/oauth2/token HTTP/1.1",
"Host: accounts.google.com",
"Content-type: application/atom+xml;charset=\"utf-8\"",
"Accept: text/xml",
"Cache-Control: no-cache", 
"code=[my_code]&client_id=[my_client_id]&client_secret=[my_client_secret]& redirect_uri=http://localhost/curl_resp.php&grant_type=authorization_code",
"Content-length: ".strlen($text),
);


 $xml_do = curl_init();
 curl_setopt($xml_do, CURLOPT_URL, $URL);
 curl_setopt($xml_do, CURLOPT_CONNECTTIMEOUT, 10);
 curl_setopt($xml_do, CURLOPT_TIMEOUT, 10);
 curl_setopt($xml_do, CURLOPT_RETURNTRANSFER, true);
 curl_setopt($xml_do, CURLOPT_SSL_VERIFYPEER, false);
 curl_setopt($xml_do, CURLOPT_SSL_VERIFYHOST, false);
 curl_setopt($xml_do, CURLOPT_POST, false);
 curl_setopt($xml_do, CURLOPT_POSTFIELDS, $text);
 curl_setopt($xml_do, CURLOPT_HTTPHEADER, $header);

我遇到了无效请求错误

【问题讨论】:

  • 在您发送到服务器的数据中,POST 正文中& 字符后面的那些新行是否存在?因为他们不应该……
  • PHP 代码看起来并不完整,并不是说它难以阅读。编辑您的问题并将您的 PHP 作为代码块添加到那里。
  • 我添加了oauthgoogle-authentication 标签。在我看来,这个问题并非专门针对 PHP、POST 方法或 cURL。在我看来,请求可以毫无问题地到达他们的服务器,但由于某种原因被他们的服务器拒绝。我发现了一个类似的帖子可能对您有所帮助:groups.google.com/group/HealthGraph/browse_thread/thread/…

标签: php post curl oauth google-api


【解决方案1】:

对您的请求的响应实际上包含对问题的非常易读的描述:

POST 请求需要 Content-length 标头。

【讨论】:

  • $text ='test'; $URL = "accounts.google.com/o/oauth2/token"; $header = array("POST /o/oauth2/token HTTP/1.1", "Host: accounts.google.com", "Content-type: application/atom+xml;charset=\"utf-8\"", “接受:文本/xml”、“缓存控制:无缓存”、“代码=[my_code]&client_id=[my_client_id]&client_secret=[my_client_secret]&redirect_uri=localhost/curl_resp.php&grant_type=authorization_code”、“内容长度:”.strlen( $text), );
  • 我使用 Google api php 客户端库来获取访问令牌,它对我有用。
【解决方案2】:

为什么将 CURLOPT_POST 设置为 false

 curl_setopt($xml_do, CURLOPT_POST, false);

虽然如果设置了 CURLOPT_POSTFIELDS,某些 cURL 配置会自动将其更改为 tru,但您没有有效的 postfield。

要在 HTTP“POST”操作中发布的完整数据。要发布文件,请在文件名前加上 @ 并使用完整路径。可以通过使用格式为“;type=mimetype”的文件名来明确指定文件类型。此参数可以作为 urlencoded 字符串(如 'para1=val1&para2=val2&...')或作为字段名称作为键和字段数据作为值的数组传递。如果 value 是一个数组,则 Content-Type 标头将设置为 multipart/form-data。从 PHP 5.2.0 开始,如果文件以 @ 前缀传递给此选项,则 value 必须是数组。

它应该是 param=value 语法或传递的数组。

【讨论】:

    【解决方案3】:

    我对使用 Google 的 oAuth API 一无所知,但从我目前看到的示例来看,您似乎应该传递值(即 codeclient_id 等)在 post 字段中,而不是直接在 HTTP 标头中。

    下面的例子仍然不能完全工作,但它没有得到invalid_request 错误,而是给你invalid_grant。我认为除了我提到的内容之外还有其他问题(也许您需要来自 Google 的新凭据或其他东西),但这可能会让您更近一步,至少:

    $post = array(
        "grant_type" => "authorization_code", 
        "code" => "your_code", 
        "client_id" => "your_client_id", 
        "client_secret" => "your_client_secret", 
        "redirect_uri" => "http://localhost/curl_resp.php"
    );
    
    $postText = http_build_query($post);
    
    $url = "https://accounts.google.com/o/oauth2/token";
    
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postText); 
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    
    $result = curl_exec($ch);
    var_dump($result);    // gets an error, "invalid_grant"
    

    【讨论】:

    • 澄清一下,通常“invalid_grant”是因为代码:your_code 已过期、已撤销或已用于授予 access_token(您可以使用一次);)
    • 这个答案非常有用,但我有疑问如何撤销授权码或获得新的?
    • @Yasser:检查the manual 或提出新问题,如果仍不清楚。
    【解决方案4】:

    我在 CURL 方法和有效的 Google 代码中使用了 post 数组,它对我有用

    【讨论】:

      【解决方案5】:

      我也遇到了同样的问题,谷歌返回一个“invalid_xxx”。

      经过大量研究和故障排除,问题出在表单本身的编码上!不要使用函数“http_builder_query”,因为它会弄乱字符串并且谷歌无法“识别”它。示例:

      http_builder_query 输出:"code=4%252FYYUT71KJ6..."

      相比

      只是一个普通的字符串:"code=4/YYUT71KJ6..."

      这是我的工作代码,我在需要您自己的数据的位置放置了“x”(取自 google oauth authentication 并进行了修改)

          $code_from_user_login = "4/YYUT71KJ6....";
          $ch = curl_init();
      
              curl_setopt($ch, CURLOPT_URL, "https://accounts.google.com/o/oauth2/token");
              curl_setopt($ch, CURLOPT_POST, TRUE);
              curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
      
      
              $post_params = "code=" . $code_from_user_login . "&";
              $post_params .= "redirect_uri=http://www.x.com/&";
              $post_params .= "client_id=x.apps.googleusercontent.com&";
              $post_params .= "client_secret=x&";
              $post_params .= "grant_type=authorization_code&";
      
      
              curl_setopt($ch, CURLOPT_POSTFIELDS, $post_params);
              $result = curl_exec($ch);
              print($result);
      

      结果会是这样的:

        '{
        "access_token" : "ya29.AHES6ZSwJSHpTZ1t....",
        "token_type" : "Bearer",
        "expires_in" : 3599,
        "id_token" : "eyJhbGciOiJSUzI1NiIsImtpZCI6IjU0MDQxOTZlMmQzOGNjYTA2MW...."
      }'
      

      获得“access_token”后,使用以下网址访问个人资料数据: https://www.googleapis.com/oauth2/v1/userinfo?access_token=YOUR_ACCESS_TOKEN_HERE

      ~结束~

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-08-30
        • 2022-11-11
        • 2018-10-22
        • 2019-11-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多