为什么我无法使用OAuth进行身份验证?

Leo*_*lis 5 php twitter curl oauth

我写了一个非常简单的应用程序来更新我在给定条件下的推特状态.我使用了twitter文档来了解创建OAuth签名的要求以及如何构建Authorization标头.然后我用PHP中的cURL发送请求.

使用twitter开发站点上的OAuth工具,我比较了我的签名基本字符串和授权标题,两者完全相同:

签名基本字符串

POST&https%3A%2F%2Fapi.twitter.com%2F1%2Fstatuses%2Fupdate.json&oauth_consumer_key%3DYNxxxxxxxxxxxWnfI6HA%26oauth_nonce%3D31077a3c7b7bee4e4c7e2b5185041c12%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1340729904%26oauth_token%3D2991771-4csoiO2fxmWgSxxxxxxxxxxDjWj2AbyxATtiuadNE%26oauth_version%3D1.0%26status%3Dblah%2520test%2520blah.
Run Code Online (Sandbox Code Playgroud)

授权标头

Authorization: OAuth oauth_consumer_key="YN4FLBxxxxxxxxxxI6HA", oauth_nonce="31077a3c7b7bee4e4c7e2b5185041c12", oauth_signature="M2cXepcxxxxxxxxxxAImeAjE%2FHc%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1340729904", oauth_token="2991771-4cxxxxxxxxxxSmRvjzMoooMDjWj2AbyxATtiuadNE", oauth_version="1.0"
Run Code Online (Sandbox Code Playgroud)

显然我已经用一些字符替换了x隐藏我的数据,但比较两个字符的字符会产生完全相同的结果.作为参考,我硬编码OAuth工具生成的时间戳和随机数,以便我的值可以相同以进行检查.我的访问级别设置为读取和写入.在同一页面上有一个最后的例子 - 在命令行上使用cURL运行的命令.当我运行此命令时,它完美地工作并发布到我的Twitter提要没有问题.

考虑到这一点,我相信到目前为止我创建的所有内容都很好,并且不认为我发布代码可以生成前面提到的详细信息.然而,我使用cURL进行调用的代码,我认为是罪魁祸首,但不能说明原因:

<?php
// ...
$curl = curl_init();

curl_setopt($curl, CURLOPT_URL, $baseUrl);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_HTTPHEADER, array("Authorization: $header"));
curl_setopt($curl, CURLOPT_POSTFIELDS, array('status' => $status));
$result = json_decode(curl_exec($curl));
curl_close($curl);

var_dump($result);
Run Code Online (Sandbox Code Playgroud)

请注意$baseUrl,$header$status生成签名基本字符串和授权标头时使用的变量相同,只是匹配得很好.

运行时页面的输出是:

object(stdClass)#1 (2) { ["error"]=> string(34) "Could not authenticate with OAuth." ["request"]=> string(23) "/1/statuses/update.json" }
Run Code Online (Sandbox Code Playgroud)

我希望这里有足够的细节让某人指出我正确的方向!

Leo*_*lis 3

经过更多的搜索、测试apache_request_headers()并坚持我的数据很好并且问题出在 cURL 的观念之后,我意识到 cURL 将请求设置Content-typemultipart/form-data;并添加边界信息,显然Content-Length也有更长的字段。这意味着状态没有正确发送,我猜是因为multipart/form-data;请求格式错误。

解决方案是将其作为字符串发送。例如,这有效:

curl_setopt($curl, CURLOPT_POSTFIELDS, 'status='. rawurlencode($status));
Run Code Online (Sandbox Code Playgroud)

但我发现有一种更好的方法(特别是当我想使用数组时具有多个值):

$postfields = array('status' => $status);
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($postfields));
Run Code Online (Sandbox Code Playgroud)

恕我直言,它看起来好多了。