添加 Flickr API 参数时的 oAuth “无效签名”

Posted

技术标签:

【中文标题】添加 Flickr API 参数时的 oAuth “无效签名”【英文标题】:oAuth "Invalid Signature" When Adding a Flickr API Argument 【发布时间】:2014-03-16 02:11:03 【问题描述】:

我遇到了非常常见的 oAuth“无效签名”问题。

我的语言是 php,我尝试与之交互的 API 是 Fl​​ickr。

我的目标是调用flickr.contacts.getList 方法。我可以毫无问题地调用此方法,只要我不通过 API 调用传递任何参数。一旦我添加一个参数(例如,页面),我的 oAuth 签名就会失效。

在大多数情况下,我利用其他人的代码来完成几乎所有事情 (see this blog post)。因此,我不完全了解 oAuth 签名是如何构建的,以及它是如何失效的。 这是我需要帮助的地方。

下面的代码可以正常工作。请注意,我没有传递 page 参数。

$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 收到“无效签名”响应。请注意,这次我传递的是 page 参数。

$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 方法)。

【问题讨论】:

【参考方案1】:

我想通了。 顺序很重要。

在上面的示例中,要添加到 page 参数,您必须将它添加到 $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 数组时,顺序似乎并不重要。

【讨论】:

以上是关于添加 Flickr API 参数时的 oAuth “无效签名”的主要内容,如果未能解决你的问题,请参考以下文章

使用 Google Fit api 时的 Google Oauth 2.0 RESULT_CANCELED

使用 Google Fit api 时的 Google Oauth 2.0 RESULT_CANCELED

OAuth2.0学习(5-4)新浪开放平台-微博API-使用OAuth2.0调用API

ios flickr api:未调用 Flickr 回调 URL

Javascript Flickr API帮助程序

我在用这个 flickr api 查询做啥?