1 <?xml version="1.0" encoding="UTF-8"?>
3 <!-- EN-Revision: 20779 -->
4 <sect1 id="zend.infocard.basics">
8 <classname>Zend_InfoCard</classname> コンポーネントは、
9 情報カード (Information Cards) の relying-party
11 情報カードは、インターネット上でのユーザ識別情報の管理や
13 最終的にユーザ認証を行う先のウェブサイトのことを
14 <emphasis>relying-party</emphasis> といいます。
19 あるいはインターネット上の識別メタシステムにおける情報カードの重要性については、
20 <ulink url="http://www.identityblog.com/">IdentityBlog</ulink>
24 <sect2 id="zend.infocard.basics.theory">
25 <title>基本的な使用法</title>
28 <classname>Zend_InfoCard</classname> の使用法は、
29 <classname>Zend_Auth</classname> コンポーネントの一部として
30 <classname>Zend_InfoCard</classname> 認証アダプタを使用するか、
31 あるいは単体のコンポーネントとして使用するかのいずれかです。
32 どちらの場合についても、ユーザから情報カードを受け取るには
33 HTML のログインフォームの中で次のような HTML ブロックを使用します。
36 <programlisting language="html"><![CDATA[
37 <form action="http://example.com/server" method="POST">
38 <input type='image' src='/images/ic.png' align='center'
39 width='120px' style='cursor:pointer' />
40 <object type="application/x-informationCard"
42 <param name="tokenType"
43 value="urn:oasis:names:tc:SAML:1.0:assertion" />
44 <param name="requiredClaims"
45 value="http://.../claims/privatepersonalidentifier
46 http://.../claims/givenname
47 http://.../claims/surname" />
53 この例において、<code>requiredClaims</code>
54 <code><param></code> タグで表しているのが、
55 claim (人の姓名など) と呼ばれる識別情報です。
56 これは、ウェブサイト ("relying party")
57 が情報カードによる認証を行うために必要となります。
61 上の HTML をユーザが実行する (クリックする) と、
62 ブラウザはカード選択プログラムを実行します。
63 これは、そのサイトの要求を満たす情報カードを表示させるだけでなく、
64 条件を満たす情報カードが複数存在する場合に好きなものを選択させることができます。
65 この情報カードは、指定した <acronym>URL</acronym> に <acronym>XML</acronym> ドキュメントとして
66 <code>POST</code> され、これを
67 <classname>Zend_InfoCard</classname> コンポーネントで処理することになります。
71 情報カードは、<acronym>SSL</acronym> で暗号化した <acronym>URL</acronym> への
72 <code>HTTP POST</code> しかできないことに注意しましょう。
73 <acronym>SSL</acronym> による暗号化を設定する方法については、
78 <sect2 id="zend.infocard.basics.auth">
79 <title>Zend_Auth の部品としての使用法</title>
82 このコンポーネントを <classname>Zend_Auth</classname>
84 <classname>Zend_Auth_Adapter_InfoCard</classname> を使用する必要があります
85 (これは、単体で配布されている <classname>Zend_InfoCard</classname>
90 <programlisting language="php"><![CDATA[
92 if (isset($_POST['xmlToken'])) {
94 $adapter = new Zend_Auth_Adapter_InfoCard($_POST['xmlToken']);
96 $adapter->addCertificatePair('/usr/local/Zend/apache2/conf/server.key',
97 '/usr/local/Zend/apache2/conf/server.crt');
100 $auth = Zend_Auth::getInstance();
102 $result = $auth->authenticate($adapter);
104 switch ($result->getCode()) {
105 case Zend_Auth_Result::SUCCESS:
106 $claims = $result->getIdentity();
107 print "Given Name: {$claims->givenname}<br />";
108 print "Surname: {$claims->surname}<br />";
109 print "Email Address: {$claims->emailaddress}<br />";
110 print "PPI: {$claims->getCardID()}<br />";
112 case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID:
113 print "The Credential you provided did not pass validation";
116 case Zend_Auth_Result::FAILURE:
117 print "There was an error processing your credentials.";
121 if (count($result->getMessages()) > 0) {
123 var_dump($result->getMessages());
130 <div id="login" style="font-family: arial; font-size: 2em;">
131 <p>Simple Login Demo</p>
133 <input type="submit" value="Login" />
134 <object type="application/x-informationCard" name="xmlToken">
135 <param name="tokenType"
136 value="urn:oasis:names:tc:SAML:1.0:assertion" />
137 <param name="requiredClaims"
138 value="http://.../claims/givenname
139 http://.../claims/surname
140 http://.../claims/emailaddress
141 http://.../claims/privatepersonalidentifier" />
149 <classname>Zend_Auth_Adapter_InfoCard</classname> のインスタンスを作成して、
150 カードセレクタから送信された <acronym>XML</acronym> データをそこに渡しています。
151 インスタンスを作成したら、次に <acronym>SSL</acronym> 証明書の秘密鍵/公開鍵
153 このペアは、<code>HTTP POST</code>
154 を受け取ったウェブサーバで使用しているものです。
155 これらのファイルを使用して、サーバに送信された情報のあて先の検証を行います。
156 情報カードを使用するときにはこれらが必要となります。
161 <classname>Zend_Auth</classname> の標準機能を使って情報カードトークンの検証を行い、
162 <methodname>getIdentity()</methodname> で取得した識別情報をもとにユーザの認証を行います。
166 <sect2 id="zend.infocard.basics.standalone">
167 <title>Zend_InfoCard コンポーネント単体での使用法</title>
170 <classname>Zend_InfoCard</classname> コンポーネントを、
171 それ単体で使用することも可能です。その場合は
172 <classname>Zend_InfoCard</classname> クラスを直接操作します。
173 <classname>Zend_InfoCard</classname> クラスの使用法は、<classname>Zend_Auth</classname>
174 コンポーネントと組み合わせて使用する場合とほぼ同じです。
178 <programlisting language="php"><![CDATA[
180 if (isset($_POST['xmlToken'])) {
181 $infocard = new Zend_InfoCard();
182 $infocard->addCertificatePair('/usr/local/Zend/apache2/conf/server.key',
183 '/usr/local/Zend/apache2/conf/server.crt');
185 $claims = $infocard->process($_POST['xmlToken']);
187 if($claims->isValid()) {
188 print "Given Name: {$claims->givenname}<br />";
189 print "Surname: {$claims->surname}<br />";
190 print "Email Address: {$claims->emailaddress}<br />";
191 print "PPI: {$claims->getCardID()}<br />";
193 print "Error Validating identity: {$claims->getErrorMsg()}";
198 <div id="login" style="font-family: arial; font-size: 2em;">
199 <p>Simple Login Demo</p>
201 <input type="submit" value="Login" />
202 <object type="application/x-informationCard" name="xmlToken">
203 <param name="tokenType"
204 value="urn:oasis:names:tc:SAML:1.0:assertion" />
205 <param name="requiredClaims"
206 value="http://.../claims/givenname
207 http://.../claims/surname
208 http://.../claims/emailaddress
209 http://.../claims/privatepersonalidentifier" />
216 上の例では、<classname>Zend_InfoCard</classname>
217 コンポーネントを単体で使用して、ユーザが送信したトークンを検証しています。
218 <classname>Zend_Auth_Adapter_InfoCard</classname> の場合と同様、
219 <classname>Zend_InfoCard</classname> のインスタンスを作成してから
220 ウェブサーバの <acronym>SSL</acronym> 証明書の公開キー/秘密キーペアを設定します。
221 設定がすんだら、<methodname>process()</methodname>
222 メソッドで情報カードの処理を行ってその結果を返します。
226 <sect2 id="zend.infocard.basics.claims">
227 <title>Claims オブジェクトの使用法</title>
230 <classname>Zend_InfoCard</classname> の使用方法
231 (単体で使用するか、あるいは <classname>Zend_Auth</classname> の一部として
232 <classname>Zend_Auth_Adapter_InfoCard</classname> 経由で使用するか)
234 <classname>Zend_InfoCard_Claims</classname> オブジェクトとして返されます。
235 このオブジェクトには assertions (claims) が含まれます。
236 これは、ユーザ認証の際にあなたのサイトが出した要求にもとづいて、
237 ユーザが送信したデータから作成したものです。
238 上の例で示したように、情報カードの妥当性を確認するには
239 <methodname>Zend_InfoCard_Claims::isValid()</methodname>
240 メソッドをコールします。claims そのものを取得するには、
241 単純に識別子 (<code>givenname</code> など)
242 をオブジェクトのプロパティとして指定してアクセスするか、
243 あるいは <methodname>getClaim()</methodname> メソッドを使用します。
247 ほとんどの場合においては <methodname>getClaim()</methodname>
249 しかし、もし <code>requiredClaims</code>
250 が複数の異なるソース/名前空間からの情報を要求している場合は、
251 それをこのメソッドで明示的に取り出す必要があります
252 (claim の完全な <acronym>URI</acronym> を私、情報カードの中からその値を取得します)。
253 一般論として、<classname>Zend_InfoCard</classname>
254 コンポーネントがデフォルトで設定する claim 用 <acronym>URI</acronym>
255 は情報カードの中で最もよく用いられるものです。
256 この場合は単純にプロパティを使用してアクセスできます。
260 検証処理の中で開発者が行わなければならない部分は、
261 情報カード内の claim の発行元を調べて
262 それが信頼できる情報元かどうかを判定するところです。
263 これを行うために、<classname>Zend_InfoCard_Claims</classname>
264 オブジェクトには <methodname>getIssuer()</methodname> メソッドが用意されています。
265 このメソッドは、情報カードの claim の発行元 <acronym>URI</acronym> を返します。
269 <sect2 id="zend.infocard.basics.attaching">
270 <title>既存のアカウントへの情報カードの添付</title>
273 既存の認証システムに情報カードのサポートを追加することもできます。
274 そのためには、private personal identifier
275 (PPI) を昔ながらの認証アカウントに埋め込み、
277 <code>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier</code>
278 をリクエストの <code>requiredClaims</code>
279 に指定します。この claim が要求されると、
280 <classname>Zend_InfoCard_Claims</classname>
281 オブジェクトはそのカード用の一意な識別子を用意します。
282 これは、<methodname>getCardID()</methodname> メソッドによって行います。
286 情報カードを既存の昔ながらの認証アカウントに添付する例を、
290 <programlisting language="php"><![CDATA[
292 public function submitinfocardAction()
294 if (!isset($_REQUEST['xmlToken'])) {
295 throw new ZBlog_Exception('Expected an encrypted token ' .
296 'but was not provided');
299 $infoCard = new Zend_InfoCard();
300 $infoCard->addCertificatePair(SSL_CERTIFICATE_PRIVATE,
301 SSL_CERTIFICATE_PUB);
304 $claims = $infoCard->process($request['xmlToken']);
305 } catch(Zend_InfoCard_Exception $e) {
306 // TODO Error processing your request
310 if ($claims->isValid()) {
311 $db = ZBlog_Data::getAdapter();
313 $ppi = $db->quote($claims->getCardID());
314 $fullname = $db->quote("{$claims->givenname} {$claims->surname}");
316 $query = "UPDATE blogusers
318 real_name = $fullname
319 WHERE username='administrator'";
323 } catch(Exception $e) {
324 // TODO Failed to store in DB
327 $this->view->render();
331 ZBlog_Exception("Infomation card failed security checks");
337 <sect2 id="zend.infocard.basics.adapters">
338 <title>Zend_InfoCard アダプタの作成</title>
341 <classname>Zend_InfoCard</classname> コンポーネントは、
342 情報カードの標準規格の変化に対応するために
344 現時点では、拡張ポイントの多くは未使用ですので無視できますが、
345 情報カードの実装においてひとつだけ実装すべき点があります。
346 それが <classname>Zend_InfoCard_Adapter</classname> です。
350 <classname>Zend_InfoCard</classname> アダプタは、
351 コンポーネント内でコールバックを使用してさまざまな処理を行います。
352 たとえば、コンポーネントが情報カードを処理する際の
353 Assertion ID の保存や取得などを行います。
354 受け取った情報カードの assertion ID の保存は必須ではありませんが、
355 もしそれに失敗すると、リプレイ攻撃によって認証が信頼できないものになる可能性が発生します。
360 <classname>Zend_InfoCard_Adapter_Interface</classname>
362 <methodname>process()</methodname> メソッド (単体) あるいは <methodname>authenticate()</methodname>
363 メソッド (<classname>Zend_Auth</classname> アダプタ) をコールしなければなりません。
364 このインターフェイスを設定するためのメソッドが
365 <methodname>setAdapter()</methodname> です。
366 以下の例では、<classname>Zend_InfoCard</classname>
367 アダプタを設定してアプリケーション内で使用しています。
370 <programlisting language="php"><![CDATA[
371 class myAdapter implements Zend_InfoCard_Adapter_Interface
373 public function storeAssertion($assertionURI,
377 /* Store the assertion and its conditions by ID and URI */
380 public function retrieveAssertion($assertionURI, $assertionID)
382 /* Retrieve the assertion by URI and ID */
385 public function removeAssertion($assertionURI, $assertionID)
387 /* Delete a given assertion by URI/ID */
391 $adapter = new myAdapter();
393 $infoCard = new Zend_InfoCard();
394 $infoCard->addCertificatePair(SSL_PRIVATE, SSL_PUB);
395 $infoCard->setAdapter($adapter);
397 $claims = $infoCard->process($_POST['xmlToken']);