サンプルの中身をみる
では、それぞれの動きについてみていきましょう。PHP-OpenIDはかなり高機能で、ほとんどのことを自動で行ってくれます。特にConsumerのサンプルは非常にシンプルだといえるでしょう。
まずindex.phpですが、こちらは単なる入力フォームを提供するだけの機能しかありません。「$msg」や「$error」など、いくつかの変数が存在していた場合に、それを表示する仕組みが用意されています。これは認証に成功や失敗した際などに利用されるもので、index.phpをincludeして使うために、用意されています。
FORM要素の送信先(action属性)には「try_auth.php」が指定されています。openid_identifierというクエリパラメータにIdentifierのURLが入ってtry_auth.phpが呼び出されることがわかります。
一番重要なのが、この「try_auth.php」です。こちらはOpenIDの認証処理のほぼすべてが含まれており、完全にPHPのコードのみで記述されています。なお処理の一部は、require_onceによって呼び出される「common.php」の内部に記述されています。
続いて、処理の基本的な流れを紹介します。処理はrun関数の中で行われ、その中で呼び出される「getConsumer(common.phpで定義されています)」で、Auth_OpenID_Consumerというクラスのインスタンスが生成されます。これがその名の通り、Consumerの処理を行うクラスです。
インスタンス生成の際に、認証情報を保存するための$storeオブジェクトを指定しています。このオブジェクトによって、情報の保存場所を変更できます。サンプルでは、getStore関数(common.php)内でAuth_OpenID_FileStoreクラスのインスタンスを生成し、ファイルとしてデータを保存しています。
PHP-OpenIDにはこれ以外にも、MySQLに保存する「Auth_OpenID_MySQLStore」をはじめとして、いくつかのクラス(Auth_OpenID_OpenIDStoreを継承したもの)が用意されており、どれを利用するかで、認証情報の保存方法を変えることができます。
サンプルでは、ファイルパスとして「/tmp/_php_consumer_test」を指定しているので、認証作業をした後にこのディレクトリを見れば、利用された情報を確認できます。データの保存場所は変更可能です。
図2:Auth_OpenID_Consumerクラス、beginメソッド
(画像をクリックすると別ウィンドウに拡大図を表示します)
ここで保存される情報は、ConsumerとIdPの間でやり取りされる際の「アソシエーションハンドル」や共通暗号鍵、nonceなどです。「アソシエーションハンドル」は、エンドユーザ(ログインしようとしているユーザ)、Consumer、IdPの間でのやり取りを特定するためのデータです。
共通暗号鍵(Shared Secret)は、正しいIdPとやり取りを行っているかを確認するために利用されています。またnonceは、なりすまし攻撃を防ぐために利用されるデータです。
さて、Auth_OpenID_Consumerクラスを生成すると、今度はそのbeginメソッドを呼び出します。その際に、取得したIdentifier URLを渡します。このメソッドは、Identifier URLからIdPの情報を読み込み、IdPにassociateと呼ばれるアクセスを行います。
このアクセスは「アソシエーションハンドル」や共通鍵を取得するためのものです。ただし、ここで得られる情報はキャッシュが可能で(保存先は$storeで指定したオブジェクトです)、キャッシュが存在していれば、このアクセスは省略され、キャッシュに保存されている情報が利用されます。
beginメソッドはAuth_OpenID_AuthRequestオブジェクトを返します。ここに、PAPEなどのいくつかの情報を追加した後、WebブラウザにIdPへのアクセスを促します。その際にConsumerは、Webブラウザに対してopenid.return_toとopenid.trust_rootという2つの情報をIdPに対して送信させます。これらは、認証作業が終わった後戻ってくるべきURLと、認証の対象とするサイト(つまりConsumer)のルートURLをあらわしています。
サンプルでは、これらの情報はそれぞれcommon.phpで用意されているgetReturnToとgetTrustRootという関数を使ってセットされます。return_toにはtry_auth.phpと同じディレクトリにあるfinish_auth.phpがセットされ、結果としてIdPでの認証後にこのファイルが呼び出されます。このファイル名を書き換えることで、認証終了処理を行う先を変更できます。
getTrustRootでは、$_SERVER['SERVER_NAME']などの変数を使い、やはり同じくtry_auth.phpが存在するURLがセットされます。IdPの確認画面などではこのURLが表示されます。ただし、getTrustRootではポート番号がセットされている場合もあります。また、try_auth.phpが存在するのは「http://example.com/openid/」だけど、認証したいのは「http://example.com/」である、といった場合には適さないため、内容を適宜書き換えて利用する必要があるでしょう。
IdPが呼び出されると、そちら側で認証の処理が行われ、openid.return_toで指定されたファイル、つまりfinish_auth.phpにリダイレクトされます。
finish_auth.phpでは、再びAuth_OpenID_Consumerクラスのインスタンスを生成し、completeメソッドを呼び出してAuth_OpenID_ConsumerResponseというオブジェクトを取得します。呼び出し時のクエリ文字列の情報から、認証の成功/失敗といった状況や認証時のデータの解析結果を保持しています。
このstatusプロパティをチェックすることで、認証の成功/失敗がわかります。成功の場合はAuth_OpenID_SUCCESS、認証がキャンセルされた場合はAuth_OpenID_CANCELとなります。finish_auth.phpでは、それに応じてメッセージを変数にセットし、index.phpをincludeしてそれを表示しています。
もし、実際にログインの仕組みとしてOpenIDのConsumerを実装し、認証に成功した場合は、ユーザ情報をデータベースに書き込んだり、セッションクッキーを発行するなどの処理をして、エンドユーザをログイン状態にする必要があるでしょう。 次のページ