自從 flickr 說棄用原有的認證方式之後,我前後寫了兩篇有關於 flickr OAuth 的文章,不過,由於 OAuth 的實做方式的關係,最近又持續的踩到雷。雖然已經可以理解他的運作模式,不過對於詳細的東西還是很模糊的一塊。
所以,今天要來踩一個大雷給大家瞧瞧。
實作
首先我們知道 OAuth 的認證模式,當我們向 flickr 取得 oauth_access_token
與 oauth_access_token_secret
之後,接著我們就是要拿來與 flickr API 做溝通。我之前的筆記文章中,也有人留言來詢問關於 API 的溝通方式,也在此一併做詳細的解說。
首先,我們需要 oauth-php 這個套件,然而這次,我挑選的是 CakePHP Components 這一個,原因是,
- 他是從 oauth-php 套件擴展而來
- 所有的方法都已經包裝好
- 雖說是 CakePHP,但是其實是 Vendor
- 所以不管是不是 CakePHP 其實都可以使用
Request Token
最好的例子就是直接實做,檔案下載之後,裡面的 Vendor/OAuth 直接搬出來用即可,
<?php
define("FLICKR_CONSUMER_KEY", "/* Fill your flickr api key. */");
define("FLICKR_CONSUMER_SECRET", "/* Fill your flickr api secret. */");
define("FLICKR_REST_API", "http://api.flickr.com/services/rest");
define("FLICKR_OAUTH_HOST", "http://www.flickr.com/services");
define("FLICKR_REQUEST_TOKEN_URL", FLICKR_OAUTH_HOST . "/oauth/request_token");
define("FLICKR_AUTHORIZE_URL", FLICKR_OAUTH_HOST . "/oauth/authorize");
define("FLICKR_ACCESS_TOKEN_URL", FLICKR_OAUTH_HOST . "/oauth/access_token");
define('OAUTH_TMP_DIR', function_exists('sys_get_temp_dir') ? sys_get_temp_dir() : realpath($_ENV["TMP"]));
define('ROOT', dirname(dirname(__FILE__)));
define('DS', DIRECTORY_SEPARATOR);
define('HOST', 'http://'.$_SERVER['HTTP_HOST']);
if(session_id() == "") session_start();
require_once './OAuth/OAuthClient.php';
$flickr = new OAuthClient(FLICKR_CONSUMER_KEY, FLICKR_CONSUMER_SECRET);
$request_token = $flickr->getRequestToken(FLICKR_REQUEST_TOKEN_URL, HOST.'/flickr_callback');
if ($request_token) {
header('Location:'.FLICKR_AUTHORIZE_URL.'?'.http_build_query(array(
'oauth_token' => $request_token->key,
'perms' => 'read'
)));
$_SESSION['request_token'] = $request_token;
}
上述這個例子,會拿回暫時的 request_token
然後,我們再將 request_token
丟給 authorize
去做認證動作,用來取得我們所需要的 access_token
與 access_token_secret
這兩個東西。
在這裡我們得先把 request_token
給記錄下來。
Access Token
我們透過 getRequestToken
所傳遞的東西,有一項是專門用來做 callback
的,上述的例子是 flickr_callback
,意思就是當我做完 authorize
之後,他會返回這個網址,以利我們繼續做後續動作。
接著,我們就是要接收 access_token
的相關資料了,
<?php
define("FLICKR_CONSUMER_KEY", "/* Fill your flickr api key. */");
define("FLICKR_CONSUMER_SECRET", "/* Fill your flickr api secret. */");
define("FLICKR_REST_API", "http://api.flickr.com/services/rest");
define("FLICKR_OAUTH_HOST", "http://www.flickr.com/services");
define("FLICKR_REQUEST_TOKEN_URL", FLICKR_OAUTH_HOST . "/oauth/request_token");
define("FLICKR_AUTHORIZE_URL", FLICKR_OAUTH_HOST . "/oauth/authorize");
define("FLICKR_ACCESS_TOKEN_URL", FLICKR_OAUTH_HOST . "/oauth/access_token");
define('OAUTH_TMP_DIR', function_exists('sys_get_temp_dir') ? sys_get_temp_dir() : realpath($_ENV["TMP"]));
define('ROOT', dirname(dirname(__FILE__)));
define('DS', DIRECTORY_SEPARATOR);
define('HOST', 'http://'.$_SERVER['HTTP_HOST']);
if(session_id() == "") session_start();
require_once './OAuth/OAuthClient.php';
$flickr = new OAuthClient(FLICKR_CONSUMER_KEY, FLICKR_CONSUMER_SECRET);
$request_token = $_SESSION['request_token'];
$access_token = $this->f->getAccessToken(FLICKR_ACCESS_TOKEN_URL, $request_token);
var_dump($access_token);
這個時候,你就會拿到 access_token
與 access_token_secret
這兩個值了。你得想辦法把他存起來,因為往後的 API 呼叫,需要認證的地方,都得要用到這兩個東西。
Call API
我們以 flickr.test.login
這個 API 來測試我們剛剛的呼叫,
<?php
define("FLICKR_CONSUMER_KEY", "/* Fill your flickr api key. */");
define("FLICKR_CONSUMER_SECRET", "/* Fill your flickr api secret. */");
define("FLICKR_REST_API", "http://api.flickr.com/services/rest");
define("FLICKR_OAUTH_HOST", "http://www.flickr.com/services");
define("FLICKR_REQUEST_TOKEN_URL", FLICKR_OAUTH_HOST . "/oauth/request_token");
define("FLICKR_AUTHORIZE_URL", FLICKR_OAUTH_HOST . "/oauth/authorize");
define("FLICKR_ACCESS_TOKEN_URL", FLICKR_OAUTH_HOST . "/oauth/access_token");
define('OAUTH_TMP_DIR', function_exists('sys_get_temp_dir') ? sys_get_temp_dir() : realpath($_ENV["TMP"]));
define('ROOT', dirname(dirname(__FILE__)));
define('DS', DIRECTORY_SEPARATOR);
define('HOST', 'http://'.$_SERVER['HTTP_HOST']);
if(session_id() == "") session_start();
require_once './OAuth/OAuthClient.php';
$flickr = new OAuthClient(FLICKR_CONSUMER_KEY, FLICKR_CONSUMER_SECRET);
$access_token = '/* 剛剛拿到的 access_token_key */';
$access_token_secret = '/* 剛剛拿到的 access_token_secret */';
$params = array(
'format' => 'json',
'nojsoncallback' => 1,
'method' => 'flickr.test.login'
);
$response = $flickr->get($access_token, $access_token_secret, FLICKR_REST_API, $params);
if ($response->code === '200') {
$response = json_decode($response->body, true);
var_dump($response);
}
以上就是一個需要簽署認證的動作,所需要的呼叫方式。
地雷
由於 flickr 在使用者認證的部份,棄用了舊有的 auth
流程,但是也提供了一個過渡流程,讓你可以把舊有的 auth
改成新的 OAuth
的方式來進行。
BUT!
倘若你是使用官方頁面上的 PHP 工具,很抱歉,你得要有轉換後 APP 全滅的心理準備。
- 一旦要求轉換
OAauth
認證,舊有auth_token
在 24 小時之後失效 - 舊有
auth_token
與oauth_token
無法併用 oauth_token
要求共用金鑰(oauth_token_secret
)
是的,目前市面上,包含 flickr 本身的 API Graden 都尚未改用 OAuth 的流程來做介紹,僅止於認證流程有詳細說明而已。所以,當你想使用新的方式的時候,請用 OAuth 的套件,重新寫過你的 flickr 相關程序(眼神死
如果你開始使用 OAuth 之後,PHP 的 phpFlickr
與 PEAR::Flickr_API
請遺忘他們吧。
結語
沒事不要學人家用什麼 OAuth