我遇到了太常见的oAuth“无效签名”问题。
我的语言是PHP,我正在尝试与之交互的API是Flickr。
我的目标是调用flickr.contacts.getList方法。我可以毫无问题地调用这个方法,只要我没有通过我的API调用传递任何参数。只要我添加一个参数(例如,页面),我的oAuth签名就会失效。
在大多数情况下,我正在利用其他人的代码来做所有事情(see this blog post)。因此,我不完全了解如何构建oAuth签名以及如何使其失效。 这是我需要帮助的地方。
直接在WORKS下方的代码就好了。请注意,我没有传递页面参数。
$mt = microtime();
$rand = mt_rand();
$oauth_nonce = md5($mt . $rand);
$nonce = $oauth_nonce;
$sig_method = "HMAC-SHA1";
$timestamp = gmdate('U');
$oversion = "1.0";
$request_token_url = 'http://api.flickr.com/services/rest';
$basestring = "format=json&method=flickr.contacts.getList&nojsoncallback=1&oauth_consumer_key=".$consumer_key."&oauth_nonce=".$nonce."&oauth_signature_method=".$sig_method."&oauth_timestamp=".$timestamp."&oauth_token=".$oauth_key."&oauth_version=".$oversion;
$baseurl = "GET&".urlencode($request_token_url)."&".urlencode($basestring);
$hashkey = $consumer_secret."&".$oauth_secret;
$oauth_signature = base64_encode(hash_hmac('sha1', $baseurl, $hashkey, true));
$fields = array
(
'method'=>'flickr.contacts.getList',
'oauth_nonce'=>$nonce,
'oauth_timestamp'=>$timestamp,
'oauth_consumer_key'=>$consumer_key,
'oauth_signature_method'=>$sig_method,
'oauth_version'=>$oversion,
'oauth_signature'=>$oauth_signature,
'nojsoncallback'=>'1',
'format'=>'json',
);
$fields_string = "";
foreach($fields as $key=>$value)
{
$fields_string .= "$key=".urlencode($value)."&";
}
$fields_string = rtrim($fields_string,'&');
$url = $request_token_url."?".$fields_string;
#Make Flickr API call.
$ch = curl_init();
$timeout = 5; // set to zero for no timeout
curl_setopt ($ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
$file_contents = curl_exec($ch);
curl_close($ch);
直接下面的代码无法正常工作,因为我收到了来自Flickr的“无效签名”回复。请注意,这次我传递页面参数。
$mt = microtime();
$rand = mt_rand();
$oauth_nonce = md5($mt . $rand);
$nonce = $oauth_nonce;
$sig_method = "HMAC-SHA1";
$timestamp = gmdate('U');
$oversion = "1.0";
$request_token_url = 'http://api.flickr.com/services/rest';
$basestring = "format=json&method=flickr.contacts.getList&page=1&nojsoncallback=1&oauth_consumer_key=".$consumer_key."&oauth_nonce=".$nonce."&oauth_signature_method=".$sig_method."&oauth_timestamp=".$timestamp."&oauth_token=".$oauth_key."&oauth_version=".$oversion;
$baseurl = "GET&".urlencode($request_token_url)."&".urlencode($basestring);
$hashkey = $consumer_secret."&".$oauth_secret;
$oauth_signature = base64_encode(hash_hmac('sha1', $baseurl, $hashkey, true));
$fields = array
(
'method'=>'flickr.contacts.getList',
'oauth_nonce'=>$nonce,
'page'=>'1',
'oauth_timestamp'=>$timestamp,
'oauth_consumer_key'=>$consumer_key,
'oauth_signature_method'=>$sig_method,
'oauth_version'=>$oversion,
'oauth_token'=>$oauth_key,
'oauth_signature'=>$oauth_signature,
'nojsoncallback'=>'1',
'format'=>'json',
);
$fields_string = "";
foreach($fields as $key=>$value)
{
$fields_string .= "$key=".urlencode($value)."&";
}
$fields_string = rtrim($fields_string,'&');
$url = $request_token_url."?".$fields_string;
#Make Flickr API call.
$ch = curl_init();
$timeout = 5; // set to zero for no timeout
curl_setopt ($ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
$file_contents = curl_exec($ch);
curl_close($ch);
第一个和第二个代码示例之间的唯一区别是我在参数中添加了。我做了很多测试,这个问题与传递参数的顺序无关(顺序似乎不影响签名)。另外,我尝试过其他Flickr API方法,它们都表现出相同的行为(所以这个问题并不特定于这个特定的Flickr方法)。
答案 0 :(得分:0)
我明白了。 订单确实很重要。
在上面的示例中,要添加页面参数,您必须将其添加到 $ basestring 变量的末尾的上,像这样:
$basestring = "format=json&method=flickr.contacts.getList&page=1&nojsoncallback=1&oauth_consumer_key=".$consumer_key."&oauth_nonce=".$nonce."&oauth_signature_method=".$sig_method."&oauth_timestamp=".$timestamp."&oauth_token=".$oauth_key."&oauth_version=".$oversion."$page=1";
在定义 $ fields 数组时,顺序似乎并不重要。