早速ではありますが、はてなの認証システムを通して、ユーザーの「アクセストークン」「アクセストークンシークレット」を取得してみましょう。この「アクセストークン」「アクセストークンシークレット」を利用すると、ブックマークの追加・削除ができるようになります。
ざっくりとした説明ですが、はてなの認証はOAuth1.0という規格に沿っています。このOAuth1.0はリクエストをする際に、パラメータに合わせて「署名」を作る必要があります。この「署名」を作るための関数が下記です。$consumer_key
、$consumer_secret
を設定して下さい。$callback_url
には、このライブラリではなく、このライブラリを呼び出すプログラムを設置するURLを指定します。通常は変更しなくても大丈夫ですが、上手くいかない場合は直接、指定して下さい。
PHP
<?php
// OAuthリクエスト用の関数
function hatena_oauth( $request_url , $method , $params_b , $response_header=0 )
{
// 設定項目
$consumer_key = '' ; // コンシューマーキー
$consumer_secret = '' ; // コンシューマーシークレット
$callback_url = ( !isset($_SERVER['HTTPS']) || empty($_SERVER['HTTPS']) ? 'http://' : 'https://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ; // このプログラムを設置するURL
// リクエスト用のパラメータ
$params_a = array
(
'oauth_callback' => $callback_url ,
'oauth_consumer_key' => $consumer_key ,
'oauth_nonce' => md5( microtime() ) ,
'oauth_signature_method' => 'HMAC-SHA1' ,
'oauth_timestamp' => time() ,
'oauth_version' => '1.0' ,
);
// アクセストークンなど取得時と、データ取得時での差異をちょこちょこと調整する
if( isset( $params_b['oauth_token'] ) )
{
$params_a['oauth_token'] = $params_b['oauth_token'] ;
unset( $params_b['oauth_token'] , $params_a['oauth_callback'] ) ;
}
if( isset( $params_b['oauth_token_secret'] ) )
{
$oauth_token_secret = $params_b['oauth_token_secret'] ;
unset( $params_b['oauth_token_secret'] ) ;
}
else
{
$oauth_token_secret = '' ;
}
if( isset($params_b['oauth_verifier']) )
{
$params_a['oauth_verifier'] = $params_b['oauth_verifier'] ;
unset( $params_b['oauth_verifier'] ) ;
}
// リクエストボディの完成
$request_body = http_build_query( $params_b ) ;
// キーを作成する
$signature_key = rawurlencode( $consumer_secret ) . '&' . rawurlencode( $oauth_token_secret ) ;
// [$params_a]と[$params_b]を署名作成のため合体
$params_c = array_merge( $params_a , $params_b ) ;
// [$params_c]をアルファベット順に並び替える
ksort( $params_c ) ;
// 配列[$params_c]を[キー=値&キー=値...]の文字列に変換
$signature_params = str_replace( array( '+' , '%7E' ) , array( '%20' , '~' ) , http_build_query( $params_c , '' , '&' ) ) ;
// リクエストメソッド、リクエストURL、パラメータを、URLエンコードしてから[&]で繋ぎ、データを作成する
$signature_data = rawurlencode( $method ) . '&' . rawurlencode( $request_url ) . '&' . rawurlencode( $signature_params ) ;
// キー[$signature_key]とデータ[$signature_data]をHMAC-SHA1方式のハッシュ値に変換し、base64エンコードして、署名を作成する
$signature = base64_encode( hash_hmac( 'sha1' , $signature_data , $signature_key , true ) ) ;
// [$params_a]に署名を追加する
$params_a['oauth_signature'] = $signature ;
// ヘッダーを作成する
$header_params = http_build_query( $params_a , '' , ',' ) ;
// GETの場合、[$params_b]をリクエストURLの末尾に付ける
if( $params_b && $method=='GET' )
{
$request_url .= '?' . http_build_query( $params_b , '' , '&' ) ;
}
// コンテキストを用意
$context = array(
'http' => array(
'method' => $method ,
'header' => array(
'Authorization: OAuth ' . $header_params ,
),
)
) ;
// POSTメソッドの場合、コンテキストにリクエストボディを加える
if( $request_body && $method != 'GET' )
{
$context['http']['content'] = $request_body ;
}
// CURLでリクエスト
$curl = curl_init() ;
// オプションのセット
curl_setopt( $curl , CURLOPT_URL , $request_url ) ;
curl_setopt( $curl , CURLOPT_HEADER, 1 ) ;
curl_setopt( $curl , CURLOPT_CUSTOMREQUEST , $method ) ;
curl_setopt( $curl , CURLOPT_SSL_VERIFYPEER , false ) ; // 証明書の検証を行わない
curl_setopt( $curl , CURLOPT_RETURNTRANSFER , true ) ; // curl_execの結果を文字列で返す
curl_setopt( $curl , CURLOPT_HTTPHEADER , $context['http']['header'] ) ; // ヘッダー
if( isset($context['http']['content']) && !empty($context['http']['content']) ) // ボディ (POST時)
{
curl_setopt( $curl , CURLOPT_POSTFIELDS , $context['http']['content'] ) ;
}
curl_setopt( $curl , CURLOPT_TIMEOUT , 5 ) ; // タイムアウトの秒数
// 実行
$res1 = curl_exec( $curl ) ;
$res2 = curl_getinfo( $curl ) ;
// 終了
curl_close( $curl ) ;
// 取得したデータ
$response = substr( $res1, $res2['header_size'] ) ; // 取得したデータ(JSONなど)
$header = substr( $res1, 0, $res2['header_size'] ) ; // レスポンスヘッダー (検証に利用したい場合にどうぞ)
// 取得したデータを返却
return ( !$response_header ) ? $response : array( $response , $header ) ;
}
// GETクエリ形式の文字列を配列に変換する関数
function get_query( $data = '' )
{
// 文字列を[&]で区切って配列に変換する
$ary = explode( '&' , $data ) ;
// [&]が含まれていない場合は終了
if( 2 > count( $ary ) )
{
return false ;
}
// 文字列を配列に整形する
foreach( $ary as $items )
{
$item = explode( '=' , $items ) ;
$query[ $item[0] ] = $item[1] ;
}
// 返却
return $query ;
}
PHP
<?php
// はてな用のライブラリの読み込み
require './hatena-oauth-library.php' ;
// アプリの権限(複数の場合は[,]で区切る)
$scope = 'read_public,write_public' ;
// セッションスタート
session_start() ;
// HTML用
$html = '' ;
// はてなでの認証が終了してリダイレクト時、アクセストークンを取得
if( isset($_GET['oauth_token']) && !empty($_GET['oauth_token']) && is_string($_GET['oauth_token']) && isset($_GET['oauth_verifier']) && !empty($_GET['oauth_verifier']) && is_string($_GET['oauth_verifier']) && isset($_SESSION['oauth_token_secret']) && !empty($_SESSION['oauth_token_secret']) && is_string($_SESSION['oauth_token_secret']) )
{
// アクセストークンをリクエストする
$data = hatena_oauth( 'https://www.hatena.com/oauth/token' , 'POST' , array( 'oauth_token' => $_GET['oauth_token'] , 'oauth_token_secret' => $_SESSION['oauth_token_secret'] , 'oauth_verifier' => $_GET['oauth_verifier']) ) ;
// 配列に変換
$query = get_query( $data ) ;
// セッション終了
$_SESSION = array() ;
session_destroy() ;
// エラー判定
if( !$query )
{
$html .= '<p>アクセストークンの取得に失敗しました…。もう一度、認証をするには、<a href="' . explode( '?' , $_SERVER['REQUEST_URI'] )[0] . '">こちら</a>をクリックして下さい。</p>' ;
}
else
{
// 情報の整理
$url_name = rawurldecode( $query['url_name'] ) ;
$display_name = rawurldecode( $query['display_name'] ) ;
$oauth_token = rawurldecode( $query["oauth_token"] ) ;
$oauth_token_secret = rawurldecode( $query['oauth_token_secret'] ) ;
// 出力する
$html .= '<h2>実行結果</h2>' ;
$html .= '<dl>' ;
$html .= '<dt>ユーザーID</dt>' ;
$html .= '<dd>' . $url_name . '</dd>' ;
$html .= '<dt>名前</dt>' ;
$html .= '<dd>' . $display_name . '</dd>' ;
$html .= '<dt>アクセストークン</dt>' ;
$html .= '<dd>' . $oauth_token . '</dd>' ;
$html .= '<dt>アクセストークンシークレット</dt>' ;
$html .= '<dd>' . $oauth_token_secret . '</dd>' ;
$html .= '</dl>' ;
}
}
// 初回アクセス時、リクエストトークンを取得して、はてなの認証画面にリダイレクトする
else
{
// リクエストトークンを取得する
$data = hatena_oauth( 'https://www.hatena.com/oauth/initiate' , 'POST' , array( 'scope' => $scope ) ) ;
// 取得した文字列を変換
if( !$query = get_query( $data ) )
{
$html .= '<p>リクエストトークンの取得に失敗しました…。もしかしたら「コンシューマーキー」「コンシューマーシークレット」「権限」の設定が違っているかもしれません…。</p>' ;
}
else
{
// セッションに保存
session_regenerate_id( true ) ;
$_SESSION['oauth_token_secret'] = rawurldecode( $query['oauth_token_secret'] ) ;
// 認証画面へリダイレクト
header( 'Location: https://www.hatena.ne.jp/oauth/authorize?oauth_token=' . $query['oauth_token'] ) ;
}
}
?>
<?php
// ブラウザに[$html]を出力 (HTMLのヘッダーとフッターを付けましょう)
echo $html ;
?>
OAuth認証のデモを用意しました。認証時、アプリケーションの権限として、読み取り権限、書き込み権限を要求しています。これらは次章以降で説明する、「ブックマークの追加」「ブックマークの削除」のデモンストレーションに必要な権限なので、ご了承下さい。このアプリケーションがあなたの操作を介さず、あなたのデータにアクセスすることはありません。