【问题标题】:PHP: Curl POST request to external Oath2 APIPHP:对外部 Oauth2 API 的 Curl POST 请求
【发布时间】:2018-08-09 12:42:08
【问题描述】:

我会试着勾勒一下我们的情况:

我们卡住的库中的方法是executeRequest。 这个方法可以在https://github.com/adoy/PHP-OAuth2/blob/master/src/OAuth2/Client.php的第404行(真是讽刺)找到

现在,就像我说的,我在 PHP 方面的经验很少,所以我的调试方式只是在脚本中的给定点回显变量的状态。 尽管这可能是业余爱好者,但我至少可以验证 url 和参数是否正确。我可以打印完整的 URL(c 的虚拟参数值):

注意使用以下参数:coderedirect_urigrant_typenclient_idclient_Secret

https://oauth.smartschool.be/OAuth/index/token?code=irsyB0VSmg4V5dVjHFgdl85iRvvu3gYpsuIE4cOk&redirect_uri=https%3A%2F%2Fmycallbackurl.com%2Fmy-page%2F&grant_type=authorization_code&client_id=5d6t5ev5a6d8&client_secret=pada9c54a6sc

当您执行此请求时,您会收到一条 JSON 错误消息。这很正常,因为我不能给你我们的 client_id 和 client_secret:

{"error":"error_occured","error_description":"Client authentication failed."}

当我在浏览器中手动执行此操作时(使用正确的参数值),我得到了所需的 JSON 结果:

{"access_token":"fa4a6s4axsaxxsfacc56c4aca8acac4q6d5z4fsv","token_type":"Bearer","expires_in":3600,"refresh_token":"X5s1aq56xaq6bhz56aGY6SCb9845465czxqde56a"}

问题是,当 CURL 构建并作为 POST 请求执行时,我得到一个错误的 JSON 结果:

{"error":"error_occured","error_description":"The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed. Check the \u0022code\u0022 parameter."}

我可以验证以下 CURL 选项的状态(请注意,代码绕过了 ssl 验证,Client.php 文件中的第 462 行):

  • CURLOPT_RETURNTRANSFER = 真
  • CURLOPT_SSL_VERIFYPEER = 假
  • CURLOPT_SSL_VERIFYHOST = 假
  • CURLOPT_CUSTOMREQUEST = 'POST'
  • CURLOPT_POST = 真
  • CURLOPT_POSTFIELDS = url 编码参数字符串

示例: code=irsyB0VSmg4V5dVjHFgdl85iRvvu3gYpsuIE4cOk&redirect_uri=https%3A%2F%2Fmycallbackurl.com%2Fmy-page%2Fgrant_type=authorization_code&client_id=5d6t5ev5a6d8&client_secret=pada9c54a6sc

当像这样执行这个 Curl 处理程序时:

$result = curl_exec($ch);

他确实成功地联系了API并返回了结果,但是JSON结果显示参数错误,声称代码不正确。 但我知道这是正确的,因为当我通过浏览器手动执行请求时,它可以工作。如果你不带参数直接访问https://oauth.smartschool.be/OAuth/index/token,你会得到同样的错误。

这让我想知道 curl 是否传递了任何参数。

您能否告诉我您是否在提供的 ifno 中某处发现错误,也许是在 curl 选项中? 或者您能否指导我找到调试此 curl 执行的正确方法(请记住,我使用的是 Wordpress,如果这很重要的话)。

如果这篇文章缺少必要的信息,请告诉我。 提前谢谢你。

--编辑:

库代码由以下代码行触发(同样,虚拟客户端 ID 和密码)。这个方法可以在https://github.com/adoy/PHP-OAuth2/blob/master/src/OAuth2/Client.php的第211行找到

$client = new Client('5d6t5ev5a6d8', 'pada9c54a6sc');
$callBackUrl = 'https://mycallbackurl.com/my-page';
$myResponse = $client->getAccessToken('https://oauth.smartschool.be/OAuth/index/token', 'authorization_code', ['code'=> $_GET['code'], 'redirect_uri' => $callBackUrl]);

为了确定,我已经删除了将 header 选项放入空数组的代码。但是使用 CURLINFO_HEADER_OUT 调试时,结果保持不变。它确实默认为 Content-Type: application/x-www-form-urlencoded。 这是完整的 curl_getinfo() 数组:

数组 ( [url] => https://oauth.smartschool.be/OAuth/index/token [content_type] => 应用程序/json [http_code] => 200 [header_size] => 7414 [request_size] => 363 [filetime] => -1 [ssl_verify_result] => 0 [redirect_count] => 0 [total_time] => 0.073514 [namelookup_time] => 3.9E-5 [connect_time] => 0.006093 [pretransfer_time] => 0.028232 [size_upload] => 216 [size_download] => 231 [speed_download] => 3142 [speed_upload] => 2938 [download_content_length] => -1 [上传内容长度] => 216 [开始传输时间] => 0.073476 [redirect_time] => 0 [redirect_url] => [primary_ip] => xxx.xxx.xxx.xxx [certinfo] => 数组 () [primary_port] => xxxxx [local_ip] => xxx.xxx.xxx.xxx [local_port] => xxxxxx [request_header] => POST /OAuth/index/token HTTP/1.1 主机:oauth.smartschool.be 接受:*/* 内容长度:216 内容类型:application/x-www-form-urlencoded )

但是,结果保持不变(仍然表明根本没有传递任何参数):

Array ( [result] => Array ( [error] => error_occured [error_description] => 请求缺少必需的参数, 包含无效的参数值,包含的参数超过 一次,否则格式不正确。检查“代码”参数。 ) [代码] => 200 [content_type] => 应用程序/json )

有没有办法从这个 curl 请求中打印参数/发布字段/正文,以验证所有信息是否已发送?

-- EDIT2:

使用 Tobias 提供的 httbin.org/post 链接后,我得到了以下结果:

Array ( 
    [args] => Array 
        (
        ) 

    [data] => 
    [files] => Array 
        ( 
        ) 

    [form] => Array 
        ( 
            [client_id] => 5d6t5ev5a6d8
            [client_secret] => pada9c54a6sc
            [code] => fa4a6s4axsaxxsfacc56c4aca8acac4q6d5z4fsv
            [grant_type] => authorization_code 
            [redirect_uri] => https://mycallbackurl.com/my-page
        ) 

    [headers] => Array 
        ( 
            [Accept] => */* 
            [Connection] => close 
            [Content-Length] => 216 
            [Content-Type] => application/x-www-form-urlencoded 
            [Host] => httpbin.org 
        ) 

    [json] => 
    [origin] => 83.xxx.xx.xx
    [url] => https://httpbin.org/post 
) 

将此与 Tobias 的示例进行比较,我没有发现任何值得注意的差异。我假设这意味着我们的 POST 请求至少包含所有必需的数据。我们在这里仍然处于黑暗中,那么 API 不接受参数的可能原因是什么。如果您想出一些其他可能的解决方案,请不要犹豫,追加它们。感谢这个转储链接,这真的很有用!

【问题讨论】:

  • 你能在调用“executeRequest()”的地方加上传递给它的参数吗?
  • 我添加了触发 getAccessToken() 的行。这个方法最后调用executeRequest()。
  • 我尝试使用提供的信息 + 编辑您如何称呼它来设置 MCVE:pastebin.com/HGpW3dLx - 但是当我调用它时,我立即得到“客户端身份验证失败”。所需的响应。我正在使用 PHP 7.2.2。在您的环境中调用该脚本时是否收到错误消息?

标签: php api curl


【解决方案1】:

您在浏览器中的测试与实际代码之间存在差异:在浏览器中,您将变量作为 GET 参数传递,而在您的代码中,您发送的是 POST em> 身体。

为了调试此类问题,我经常发现在使用 PHP 之前使用 CLI curl 更容易。当我这样发送请求时(注意Content-Type 标头),我设法得到了肯定的结果:

curl -X POST --data "code=irsyB0VSmg4V5dVjHFgdl85iRvvu3gYpsuIE4cOk&redirect_uri=https%3A%2F%2Fmycallbackurl.com%2Fmy-page%2F&grant_type=authorization_code&client_id=5d6t5ev5a6d8&client_secret=pada9c54a6sc" "https://oauth.smartschool.be/OAuth/index/token" -H "Content-Type: application/x-www-form-urlencoded"
{"error":"error_occured","error_description":"Client authentication failed."}

当我在没有此标头的情况下强行发送请求时,我能够重现您的错误。这实际上并不容易,因为使用--data 会自动添加它:

curl -X POST --data "code=irsyB0VSmg4V5dVjHFgdl85iRvvu3gYpsuIE4cOk&redirect_uri=https%3A%2F%2Fmycallbackurl.com%2Fmy-page%2F&grant_type=authorization_code&client_id=5d6t5ev5a6d8&client_secret=pada9c54a6sc" "https://oauth.smartschool.be/OAuth/index/token" -H "Content-Type: "
{"error":"error_occured","error_description":"The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed. Check the \u0022grant_type\u0022 parameter."}

您需要确保您的代码发送带有标头的请求:Content-Type: application/x-www-form-urlencoded

我猜 PHP-curl 在使用 POST(FIELDS) 时也会隐式添加它(类似于 CLI 版本),您的问题可能是您“强制”将 CURLOPT_HTTPHEADER 设置为空数组并因此删除它。

要调试正在发送的标头,您可以使用:

curl_setopt($ch, CURLINFO_HEADER_OUT, true);
// curl_exec
$information = curl_getinfo($ch);
print_r($information);

编辑:

实际上更好的调试方法是将 POST 转到 https://httpbin.org/post 的 OAuth-URL。这只会镜像发送给它的所有内容,因此然后转储您获得的响应,它应该如下所示:

Array
(
    [result] => Array
        (
            [args] => Array
                (
                )

            [data] =>
            [files] => Array
                (
                )

            [form] => Array
                (
                    [client_id] => 5d6t5ev5a6d8
                    [client_secret] => pada9c54a6sc
                    [code] => irsyB0VSmg4V5dVjHFgdl85iRvvu3gYpsuIE4cOk
                    [grant_type] => authorization_code
                    [redirect_uri] => https://mycallbackurl.com/my-page
                )

            [headers] => Array
                (
                    [Accept] => */*
                    [Connection] => close
                    [Content-Length] => 180
                    [Content-Type] => application/x-www-form-urlencoded
                    [Host] => httpbin.org
                )

            [json] =>
            [origin] => 217.***.***.***
            [url] => https://httpbin.org/post
        )

    [code] => 200
    [content_type] => application/json
)

并且您有望识别从那里发送(而不是)发送的内容,包括正文数据。不幸的是,即使curls 详细模式也没有显示出来。

【讨论】:

  • 感谢您为重现问题和解释所做的努力。我在帖子中添加了更多信息,显示了 curl_getinfo 的结果。您能否再看看结果并告诉我您是否可以指出任何其他问题?谢谢你。
  • 我添加了另一种方法来使用httpbin.org从您的请求中调试所有内容。另外,我添加了一个 MCVE 作为对您的问题的评论,但它对我有用。
  • 感谢托拜厄斯的额外提示。我还没有时间进一步测试,明天再做。到目前为止,我已经为你的帮助奖励了你的赏金,否则它就会过期。到目前为止,谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-07
  • 1970-01-01
  • 2019-11-06
  • 2016-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多