2012-06-26 105 views
5

我写了一个非常简单的应用程序来更新我的twitter状态在给定的条件。我使用twitter文档来了解创建OAuth签名的要求以及如何构造授权标头。然后我用PHP中的cURL发送请求。为什么我无法使用OAuth进行身份验证?

使用在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. 

授权标头

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" 

显然我已经取代了s用x来隐藏我的数据,但是比较字符的两个字符会得到完全相同的结果。作为参考,我对OAuth工具生成的时间戳和随机数进行了硬编码,以便我的值可以与检查相同。我的访问级别设置为读取和写入。在同一页面上有一个最后的例子 - 在命令行上使用cURL运行的命令。当我运行这个命令,它完美的工作,并张贴到我的Twitter饲料没有问题。

考虑到这一点,我相信我已经创建至今,一切都很好,不觉得有什么意义我张贴的产生前面提到的细节的代码。但是,我用它来拨打电话,使用卷曲的代码,我认为是罪魁祸首,但不知道为什么:

<?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); 

注意$baseUrl$header$status在生成签名时所使用的相同的变量基本字符串和授权标头,这很好匹配。

页面的输出,当运行是:

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

我希望在这里有足够的细节有人点我在正确的方向!

+0

你看过https://dev.twitter.com/discussions/305(例如检查网址)和https://dev.twitter.com/discussions/308(例如验证HTTPS选项)吗? – Will

+0

不幸的是,是的。正如我所说的,签名基本字符串和授权标头完全相同,并且命令行卷曲完美地起作用,但它不能是其中之一。 – LeonardChallis

+0

有完全相同的问题。谢谢! – bozdoz

回答

2

后更加搜索,与apache_request_headers()测试和坚持的概念,我的数据是个好人,这是卷曲那里的问题奠定了,我意识到,卷曲经设置请求的Content-type作为multipart/form-data;并加入边界信息,很明显也有更长的Content-Length字段。这意味着状态没有得到正确的发送,我认为是因为格式错误multipart/form-data;请求。

的解决办法是将它发送一个字符串。举例来说,这个工程:

curl_setopt($curl, CURLOPT_POSTFIELDS, 'status='. rawurlencode($status)); 

但是我发现有一个更漂亮的方式(尤其是与多个值,当我想用​​一个数组):

$postfields = array('status' => $status); 
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($postfields)); 

看起来好得多恕我直言。

1

我认为这是你的nonce。从docs道:“oauth_nonce参数是一个独特的标记您的应用程序应该产生每个唯一请求”(重点煤矿)。

警告:我更熟悉OAuth 2 + Java或JavaScript的,而不是OAuth的1 + PHP。

如果这不是它(或不是唯一的东西),你可以(例如,使用的是Wireshark)比较实际的HTTP请求,他们在该网页上记载的样本请求。关于“构建标题字符串”的说明也可能有所帮助。

+0

无法区分产生现时值的人。正如我所说的,授权头和基本字符串*完全相同*,所以通过curl运行,他们不会知道/关心谁先生成该随机数。 nonce只是硬编码来比较值。我认为比较HTTP请求是一种方式,实际上我已将'baseUrl'更改为自己的页面,并使用cURL命令行与PHP cURL调用进行了测试,但没有发现任何明显的现象。 – LeonardChallis

+0

我很确定Twitter会缓存过去的随机数并拒绝重复,从而防止重播攻击。见http://oauth.net/core/1.0/#nonce:“消费者应该生成一个Nonce值,该值对于所有具有该时间戳的请求是唯一的。一个随机数是一个随机字符串,为每个请求唯一地生成。允许服务提供商验证之前从未做出请求,并有助于防止在通过非安全通道(如HTTP)进行请求时发生重放攻击。“ – Will

+1

我不认为你理解我。唯一一次硬编码nonce是比较我的授权头和签名基础字符串与twitter的生成的。我确实在测试生成的cURL请求时确定它会完成,并且它确实完成了。我不会再尝试在我的PHP脚本中再次使用相同的随机数。它**绝对不是现时**。在我的脚本中,我有一个生成唯一随机数的函数。尽管感谢您的意见。 – LeonardChallis

相关问题