<div class="section">
OAuthの実装の仕組みを理解するためにPHPでMyOAuthクラスなるものを自分で作った。
mixiの「2-legged OAuthによるAPIアクセス」を参考にしてるよ。
http://developer.mixi.co.jp/appli/spec/mob/2-legged-oauth
※「こうして生成されたパラメータをAuthorizationヘッダに追加して、APIリクエストを送信します。」ってどうやるねん!と思った。
※2-legged OAuthはTwitterで採用してるOAuthなんかと違って「ユーザが認証する」プロセスがないようです。
※追記 : クエリパラメータに ?fields=birthday,gender みたいに , 区切りがあると失敗する。なぜだ。
⇒ どうやらパラメータの , はエンコードしてはいけないらしい。というか最初にエンコードしとらしい。なので , だけはわざと二重エンコードするようにした。
my_oauth.class.php <?php /** * OAuth認証でAPIにリクエストを送信するライブラリ * * 2010-10-28 * @author Tanny */ require_once 'HTTP/Request.php' ; class MyOAuth { const OAUTH_SIGNATURE_METHOD = 'HMAC-SHA1', OAUTH_VERSION = '1.0'; private $oauth_consumer_key; //事前に発行されたconsumer_keyを設定 private $oauth_consumer_secret_key; //事前に発行されたconsumer_secret_keyを設定 private $oauth_nonce; //ランダムな文字列。必ずリクエストごとに違う値を設定してください。 private $oauth_signature; //APIリクエストの妥当性を検証するための署名 private $oauth_signature_method; //署名方式。’HMAC-SHA1′固定 private $oauth_version; //1.0 private $oauth_timestamp; //UNIXタイムスタンプ。時刻がずれているとエラーになるので、サーバの時刻設定を確認ください。 private $xoauth_requestor_id; //ViewerのIDを設定 /** * コンストラクタ * * @param $oauth_consumer_key 事前に発行されたconsumer_key * @param $oauth_consumer_secret_key 事前に発行されたconsumer_secret_key * @param $xoauth_requestor_id ViewerのID */ public function __construct($oauth_consumer_key, $oauth_consumer_secret_key, $xoauth_requestor_id) { $this->oauth_consumer_key = $oauth_consumer_key; $this->oauth_consumer_secret_key = $oauth_consumer_secret_key; $this->xoauth_requestor_id = $xoauth_requestor_id; $this->oauth_signature_method = self::OAUTH_SIGNATURE_METHOD; $this->oauth_version = self::OAUTH_VERSION; } /** * get * GETでOAuth認証をして、APIにリクエストを送信する * * @param $api_url APIのURL * @param $query_params クエリパラメータの配列 * @return APIからのレスポンス */ public function get($api_url, $query_params = array()) { return $this->request('GET', $api_url, $query_params); } /** * post * POSTでOAuth認証をして、APIにリクエストを送信する * * @param $api_url APIのURL * @param $query_params クエリパラメータの配列 * @return APIからのレスポンス */ public function post($api_url, $query_params = array()) { return $this->request('POST', $api_url, $query_params); } /** * request * OAuth認証をして、APIにリクエストを送信する * * @param $method リクエストの送信方法(GET or POST) * @param $api_url APIのURL * @param $query_params クエリパラメータの配列 * @return APIからのレスポンス */ private function request($method, $api_url, $query_params) { $this->oauth_nonce = uniqid(); //TODO この乱数生成は微妙かもしれない $this->oauth_timestamp = time(); $query_params = $this->fix_query_params($query_params); $this->oauth_signature = $this->create_oauth_signature($method, $api_url, $query_params); $request = new HTTP_Request(); $request->setUrl($api_url . '?' . $this->join_param('&', $query_params)); $request->addHeader('Authorization', $this->create_authorization_header()); if ($method === 'POST') { $request->setMethod(HTTP_REQUEST_METHOD_POST); } $response = $request->sendRequest(); if (PEAR::isError($response)) { return false; } return $request->getResponseBody(); } /** * fix_query_params * クエリパラメータにVIEWERのIDを付属させる * * @param $query_params クエリパラメータの配列 * @return VIEWERのIDを付属させたクエリパラメータの配列 */ private function fix_query_params($query_params) { $query_params['xoauth_requestor_id'] = $this->xoauth_requestor_id; return $query_params; } /** * create_oauth_signature * OAuth認証のためのシグニシャを生成する * * @param $method リクエストの送信方法(GET or POST) * @param $api_url APIのURL * @param $query_params クエリパラメータの配列 * @return OAuth認証のためのシグニシャ */ private function create_oauth_signature($method, $api_url, $query_params) { if (!$method || !$api_url) { return false; } $oauth_signature_params = array( 'oauth_consumer_key' => $this->oauth_consumer_key, 'oauth_nonce' => $this->oauth_nonce, 'oauth_signature_method' => $this->oauth_signature_method, 'oauth_timestamp' => $this->oauth_timestamp, 'oauth_version' => $this->oauth_version, ); if ($query_params) { foreach ($query_params as $key => $val) { $oauth_signature_params[$key] = $val; } } ksort($oauth_signature_params); $oauth_signature_param = $this->join_param('&', $oauth_signature_params); $base_params = array( rawurlencode($method), rawurlencode($api_url), rawurlencode($oauth_signature_param), ); $base_str = join('&', $base_params); $secret_key = $this->oauth_consumer_secret_key . '&'; return base64_encode(hash_hmac('sha1', $base_str, $secret_key, true)); } /** * create_authorization_header * Authorizationヘッダーにつける値を生成 * * @return Authorizationヘッダーにつける値 */ private function create_authorization_header() { $headers = array( 'oauth_consumer_key' => $this->oauth_consumer_key, 'oauth_signature_method' => $this->oauth_signature_method, 'oauth_signature' => $this->oauth_signature, 'oauth_timestamp' => $this->oauth_timestamp, 'oauth_nonce' => $this->oauth_nonce, 'oauth_version' => $this->oauth_version, ); ksort($headers); $authorization_header = 'OAuth realm=""'; foreach ($headers as $key => $val) { $authorization_header .= ", {$key}=\"{$val}\""; } return $authorization_header; } /** * 配列のキーと値を「=」で繋ぎ、それらを$glueで指定された文字で連結する * * @param $glue 連結文字 * @param $params 連結する連想配列 * @return @配列のキーと値を「=」で繋ぎ、それらを$glueで指定された文字で連結した配列 */ private function join_param($glue, $params) { $ary = array(); foreach ($params as $key => $val) { $ary[] = "{$key}={$val}"; } return join($glue, $ary); } } ?>
MyOAuthを使用する側 <?php require_once 'my_oauth.class.php'; $oauth = new MyOAuth(OAUTH_CONSUMER_KEY, OAUTH_CONSUMER_SECRET_KEY, VIEWER_ID); $response = $oauth->get('APIURL', ARRAY_PARAM); ?>