[PHP] OAuth with flickr

自從 flickr 說棄用原有的認證方式之後,我前後寫了兩篇有關於 flickr OAuth 的文章,不過,由於 OAuth 的實做方式的關係,最近又持續的踩到雷。雖然已經可以理解他的運作模式,不過對於詳細的東西還是很模糊的一塊。

所以,今天要來踩一個大雷給大家瞧瞧。

[PHP] Flickr OAuth PHP 認證小筆記

[PHP] Flickr OAuth PHP 認證小筆記 Part 2


實作

首先我們知道 OAuth 的認證模式,當我們向 flickr 取得 oauth_access_tokenoauth_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_tokenaccess_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_tokenaccess_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_tokenoauth_token 無法併用
  • oauth_token 要求共用金鑰(oauth_token_secret

是的,目前市面上,包含 flickr 本身的 API Graden 都尚未改用 OAuth 的流程來做介紹,僅止於認證流程有詳細說明而已。所以,當你想使用新的方式的時候,請用 OAuth 的套件,重新寫過你的 flickr 相關程序(眼神死

如果你開始使用 OAuth 之後,PHP 的 phpFlickrPEAR::Flickr_API 請遺忘他們吧。

結語

沒事不要學人家用什麼 OAuth

Hina Chen
偏執與強迫症的患者,算不上是無可救藥,只是我已經遇上我的良醫了。
Taipei