1 <?xml version="1.0" encoding="UTF-8"?>
3 <!-- EN-Revision: 20872 -->
4 <sect1 id="zend.openid.provider">
5 <title>Zend_OpenId_Provider</title>
7 <classname>Zend_OpenId_Provider</classname>
8 は、OpenID サーバを実装するために使用するものです。
9 本章では、とりあえず動作するサーバを作成するための初歩的な例を説明します。
10 しかし、実際に運用する OpenID サーバ
11 (<ulink url="http://www.myopenid.com">www.myopenid.com</ulink> などのようなもの)
12 を実装するには、より複雑な問題に対応する必要があります。
15 <sect2 id="zend.openid.provider.start">
16 <title>クイックスタート</title>
18 以下の識別子は、<classname>Zend_OpenId_Provider::register</classname>
19 を使用してユーザアカウントを作成するコードを含みます。
20 <code>rel="openid.server"</code> が指定されているリンク要素は、
21 自前のサーバスクリプトを指しています。この識別子を OpenID
22 対応のサイトに送信すると、このサーバ上での認証を行います。
26 <html> より前のコードは、
27 自動的にユーザアカウントを作成するためのちょっとしたおまじないです。
28 実際の識別子を使用する場合は、このようなコードは不要です。
31 <example id="zend.openid.provider.example-1">
33 <programlisting language="php"><![CDATA[
36 define("TEST_SERVER", Zend_OpenId::absoluteURL("example-8.php"));
37 define("TEST_ID", Zend_OpenId::selfURL());
38 define("TEST_PASSWORD", "123");
39 $server = new Zend_OpenId_Provider();
40 if (!$server->hasUser(TEST_ID)) {
41 $server->register(TEST_ID, TEST_PASSWORD);
45 <link rel="openid.server" href="<?php echo TEST_SERVER;?>" />
53 次の識別サーバスクリプトは、OpenID 対応のサイトからの二種類のリクエスト
54 (関連付けと認証) を処理します。どちらについても、同じメソッド
55 <classname>Zend_OpenId_Provider::handle</classname> で処理します。
56 <classname>Zend_OpenId_Provider</classname> へ渡すふたつの引数は
57 ログイン <acronym>URL</acronym> と信頼済みページの <acronym>URL</acronym> で、
58 これらはエンドユーザから指定されたものです。
62 成功した場合、<classname>Zend_OpenId_Provider::handle</classname>
63 メソッドは文字列を返します。これはそのまま OpenID
65 失敗した場合は <constant>FALSE</constant> を返します。
66 この例では、失敗した場合に <acronym>HTTP</acronym> 403 レスポンスを返しています。
67 このページをウェブブラウザで表示しようとすると、
68 <acronym>HTTP</acronym> 403 レスポンスが返されます。リクエストが
72 <example id="zend.openid.provider.example-2">
73 <title>シンプルな識別プロバイダ</title>
74 <programlisting language="php"><![CDATA[
75 $server = new Zend_OpenId_Provider("example-8-login.php",
76 "example-8-trust.php");
77 $ret = $server->handle();
78 if (is_string($ret)) {
80 } else if ($ret !== true) {
81 header('HTTP/1.0 403 Forbidden');
89 この処理、そしてその後の対話形式のスクリプトではセキュアな接続
96 次のスクリプトは、識別サーバ <classname>Zend_OpenId_Provider</classname>
98 ユーザがまだログインしていない場合は、このページにリダイレクトします。
99 このページでユーザがパスワードを入力してログインを行います。
103 この識別子スクリプトからのユーザ登録時のパスワードは "123" です。
107 送信すると、このスクリプトは <classname>Zend_OpenId_Provider::login</classname>
108 にエンドユーザの識別子とパスワードを渡し、識別プロバイダのスクリプトにリダイレクトします。
109 成功した場合、<classname>Zend_OpenId_Provider::login</classname>
110 はエンドユーザと識別プロバイダの間のセッションを確立し、
113 (別の OpenID 対応ウェブサイトからのものであったとしても)
119 このセッションは、エンドユーザと識別プロバイダの間だけのものであることに注意しましょう。
120 OpenID 対応のサイトは、このセッションについて何も知ることができません。
124 <example id="zend.openid.provider.example-3">
125 <title>シンプルなログイン画面</title>
126 <programlisting language="php"><![CDATA[
128 $server = new Zend_OpenId_Provider();
130 if ($_SERVER['REQUEST_METHOD'] == 'POST' &&
131 isset($_POST['openid_action']) &&
132 $_POST['openid_action'] === 'login' &&
133 isset($_POST['openid_identifier']) &&
134 isset($_POST['openid_password'])) {
135 $server->login($_POST['openid_identifier'],
136 $_POST['openid_password']);
137 Zend_OpenId::redirect("example-8.php", $_GET);
144 <legend>OpenID ログイン</legend>
150 name="openid_identifier"
151 value="<?php echo htmlspecialchars($_GET['openid_identity']);?>">
158 name="openid_password"
179 ユーザがログインしているというだけでは、認証が成功したとは言い切れません。
180 個々の OpenID 対応サイトについて、
181 それを信頼するかどうかをユーザが決めることができます。
182 次の信頼画面は、エンドユーザにそれを選択させるものです。
183 この選択は、現在のリクエストのみ行うか、あるいは
185 後者の場合は、信頼するサイト/しないサイト
187 このサイトからの次回以降の認証リクエストは自動的に処理されるようになります。
190 <example id="zend.openid.provider.example-4">
191 <title>シンプルな信頼画面</title>
192 <programlisting language="php"><![CDATA[
194 $server = new Zend_OpenId_Provider();
196 if ($_SERVER['REQUEST_METHOD'] == 'POST' &&
197 isset($_POST['openid_action']) &&
198 $_POST['openid_action'] === 'trust') {
200 if (isset($_POST['allow'])) {
201 if (isset($_POST['forever'])) {
202 $server->allowSite($server->getSiteRoot($_GET));
204 $server->respondToConsumer($_GET);
205 } else if (isset($_POST['deny'])) {
206 if (isset($_POST['forever'])) {
207 $server->denySite($server->getSiteRoot($_GET));
209 Zend_OpenId::redirect($_GET['openid_return_to'],
210 array('openid.mode'=>'cancel'));
217 <a href="<?php echo htmlspecialchars($server->getSiteRoot($_GET));?>">
218 <?php echo htmlspecialchars($server->getSiteRoot($_GET));?>
221 <a href="<?php echo htmlspecialchars($server->getLoggedInUser());?>">
222 <?php echo htmlspecialchars($server->getLoggedInUser());?>
227 <input type="checkbox" name="forever">
228 <label for="forever">永久に</label><br>
229 <input type="hidden" name="openid_action" value="trust">
230 <input type="submit" name="allow" value="許可する">
231 <input type="submit" name="deny" value="拒否する">
239 実際に運用されている OpenID サーバは、通常は Simple Registration
242 コンシューマがプロバイダに問い合わせることが可能となります。
243 この場合、信頼済みのページではユーザの情報を取得できるようになります。
247 <sect2 id="zend.openid.provider.all">
248 <title>すべてを組み合わせる</title>
250 プロバイダのすべての関数をひとつのスクリプトにまとめることもできます。
251 この場合はログイン <acronym>URL</acronym> と信頼済み <acronym>URL</acronym> は省略され、
252 <classname>Zend_OpenId_Provider</classname> は同一ページに GET 引数
253 "openid.action" を追加した場所を指すことになります。
260 エンドユーザ向けの GUI を提供していませんが、
262 これはサンプルをできるだけシンプルにするための処置であり、
263 実際のサーバでは、先ほどのサンプルのようなコードも必要となります。
267 <example id="zend.openid.provider.example-5">
268 <title>すべてをまとめたもの</title>
269 <programlisting language="php"><![CDATA[
270 $server = new Zend_OpenId_Provider();
272 define("TEST_ID", Zend_OpenId::absoluteURL("example-9-id.php"));
273 define("TEST_PASSWORD", "123");
275 if ($_SERVER['REQUEST_METHOD'] == 'GET' &&
276 isset($_GET['openid_action']) &&
277 $_GET['openid_action'] === 'login') {
278 $server->login(TEST_ID, TEST_PASSWORD);
279 unset($_GET['openid_action']);
280 Zend_OpenId::redirect(Zend_OpenId::selfUrl(), $_GET);
281 } else if ($_SERVER['REQUEST_METHOD'] == 'GET' &&
282 isset($_GET['openid_action']) &&
283 $_GET['openid_action'] === 'trust') {
284 unset($_GET['openid_action']);
285 $server->respondToConsumer($_GET);
287 $ret = $server->handle();
288 if (is_string($ret)) {
290 } else if ($ret !== true) {
291 header('HTTP/1.0 403 Forbidden');
299 この例を先ほどの複数ページ分割版と比べてみると、
300 振り分け処理のコード以外の違いは一か所だけであることに気づかれることでしょう。
301 そう。<methodname>unset($_GET['openid_action'])</methodname> の部分です。
302 この <code>unset</code> は、次のリクエストをメインハンドラにまわすために必要となります。
306 <sect2 id="zend.openid.provider.sreg">
307 <title>Simple Registration Extension</title>
309 次に示す識別子ページには、またもやおまじないが組み込まれています。
310 ここでは新たなユーザアカウントの作成を行い、それをプロファイル
311 (ニックネームとパスワード) と関連付けています。
312 実際の環境ではこのような処理は不要です。エンドユーザは
313 OpenID サーバ上でこれらの情報を登録するからです。
314 しかし、これらの登録用の GUI の実装についてはこのマニュアルでは取り上げません。
317 <example id="zend.openid.provider.example-6">
318 <title>プロファイルを関連付けた識別子</title>
319 <programlisting language="php"><![CDATA[
321 define("TEST_SERVER", Zend_OpenId::absoluteURL("example-10.php"));
322 define("TEST_ID", Zend_OpenId::selfURL());
323 define("TEST_PASSWORD", "123");
324 $server = new Zend_OpenId_Provider();
325 if (!$server->hasUser(TEST_ID)) {
326 $server->register(TEST_ID, TEST_PASSWORD);
327 $server->login(TEST_ID, TEST_PASSWORD);
328 $sreg = new Zend_OpenId_Extension_Sreg(array(
330 'email' => 'test@test.com'
332 $root = Zend_OpenId::absoluteURL(".");
333 Zend_OpenId::normalizeUrl($root);
334 $server->allowSite($root, $sreg);
340 <link rel="openid.server" href="<?php echo TEST_SERVER;?>" />
343 <?php echo TEST_ID;?>
350 この識別子を OpenID 対応のサイト (ここでは、先ほどの章の
351 Simple Registration Extension のサンプルを使用します)
352 に渡し、そのサイトは次の OpenID サーバスクリプトを使用します。
356 これは、先ほどの "すべてを組み合わせる" 例を少し変更したものです。
357 自動ログインの仕組みは同様に使用していますが、
358 信頼済みページに関する情報は含んでいません。
359 ユーザは既に、このサンプルのスクリプトを "永久に" 信頼しています。
361 <methodname>Zend_OpenId_Provider::alowSite</methodname> メソッドです。
362 同じメソッドでプロファイルと信頼済み <acronym>URL</acronym> を関連付け、
363 信頼済み <acronym>URL</acronym> からリクエストがあった場合にこのプロファイルが自動的に返されます。
367 Simple Registration Extension を動作させるために唯一必要なのは、
368 <classname>Zend_OpenId_Extension_Sreg</classname> のオブジェクトを
369 <methodname>Zend_OpenId_Provider::handle</methodname> の 2 番目の引数として渡すことです。
372 <example id="zend.openid.provider.example-7">
373 <title>SREG を使用したプロバイダ</title>
374 <programlisting language="php"><![CDATA[
375 $server = new Zend_OpenId_Provider();
376 $sreg = new Zend_OpenId_Extension_Sreg();
378 define("TEST_ID", Zend_OpenId::absoluteURL("example-10-id.php"));
379 define("TEST_PASSWORD", "123");
381 if ($_SERVER['REQUEST_METHOD'] == 'GET' &&
382 isset($_GET['openid_action']) &&
383 $_GET['openid_action'] === 'login') {
384 $server->login(TEST_ID, TEST_PASSWORD);
385 unset($_GET['openid_action']);
386 Zend_OpenId::redirect(Zend_OpenId::selfUrl(), $_GET);
387 } else if ($_SERVER['REQUEST_METHOD'] == 'GET' &&
388 isset($_GET['openid_action']) &&
389 $_GET['openid_action'] === 'trust') {
392 $ret = $server->handle(null, $sreg);
393 if (is_string($ret)) {
395 } else if ($ret !== true) {
396 header('HTTP/1.0 403 Forbidden');
404 <sect2 id="zend.openid.provider.else">
405 <title>それ以外には?</title>
408 OpenID 対応のサイトの作成ほど頻繁に行うものではありません。
409 そこで、<classname>Zend_OpenId_Consumer</classname> のマニュアルとは異なり
410 <classname>Zend_OpenId_Provider</classname> のマニュアルではすべての機能を網羅することをやめます。
414 残っている機能について簡単にまとめると、次のようになります。
420 エンドユーザ向けの GUI インターフェイスを作成するためのメソッド群。
421 ユーザの登録、信頼済みサイトやプロファイルの設定などを行えるようにします。
426 ユーザやサイト、プロファイルといった情報を格納するための抽象化された保存レイヤ。
427 ここには、プロバイダと OpenID 対応サイトとの関連付け情報も保存します。
428 このレイヤは <classname>Zend_OpenId_Consumer</classname>
430 デフォルトではファイルストレージを使用しますが、
436 エンドユーザのウェブブラウザとログイン識別子を関連付けるための、
443 <classname>Zend_OpenId_Provider</classname> は、
444 OpenID サーバが実装できる全機能をサポートしているわけではありません
446 <classname>Zend_OpenId_Extension</classname> を使用したり子クラスを作成したりして、