1 <?xml version="1.0" encoding="UTF-8"?>
3 <!-- EN-Revision: 20763 -->
4 <sect1 id="zend.acl.introduction">
8 <classname>Zend_Acl</classname> は、軽量で柔軟なアクセス制御リスト (<acronym>ACL</acronym>)
9 機能と権限管理機能を提供します。アプリケーションでは一般に、
10 保護されたオブジェクトへのアクセスを制御するためにこれらの機能を使用します。
20 <emphasis>リソース (Resource)</emphasis>
21 とは、アクセス制御の対象となるオブジェクトのことです。
26 <emphasis>ロール (Role)</emphasis>
27 とは、リソースに対してのアクセスを要求するオブジェクトのことです。
33 簡単に言うと、<emphasis>ロールがリソースに対してのアクセスを要求する</emphasis>
34 ということです。たとえば、ある人が自動車を利用したいと考えているとしましょう。
35 この場合、自動車を誰が利用できるのかが管理されているとすると
36 「ある人」がロールで「自動車」がリソースとなります。
40 アクセス制御リスト (<acronym>ACL</acronym>) での設定によって、アプリケーションは
41 要求してきたオブジェクト (ロール) が制限されたオブジェクト (リソース)
42 へのアクセスを認められているかどうかを制御します。
45 <sect2 id="zend.acl.introduction.resources">
48 <classname>Zend_Acl</classname> では、リソースを作成するのは簡単です。<classname>Zend_Acl</classname> の
49 <classname>Zend_Acl_Resource_Interface</classname> に、
50 開発者がリソースを作成するの手助けする機能が含まれています。
51 リソースクラスは、単にこのインターフェイスを実装するだけで作成できます。
52 このインターフェイスに含まれるメソッドはひとつだけで、それは
53 <methodname>getResourceId()</methodname> です。このメソッドにより、
54 <classname>Zend_Acl</classname> ではそのオブジェクトがリソースであると判断します。さらに、
55 基本的なリソースの実装を含む <classname>Zend_Acl_Resource</classname>
56 が <classname>Zend_Acl</classname> にインクルードされています。
57 開発者は、必要な部分だけを拡張することでリソースを作成できます。
60 <classname>Zend_Acl</classname> は、ツリー構造を提供しています。これを用いて複数のリソース
61 ("アクセス制御されているエリア") を追加できます。
62 リソースはこのようにツリー構造で管理されるので、全般的なもの
63 (ルートに近いほう) から特殊なもの (末端に近いほう) までを扱うことができます。
65 リソースの階層をたどって自動的に上位階層への問い合わせも行われます。
66 これにより、規則を階層化して管理すること実現できます。
67 たとえば、ある都市のすべての建物に適用されるデフォルトの規則がある場合に、
68 それを各建物に適用する代わりに都市に対して適用することができるようになります。
69 中にはこの規則の例外となる建物もあるかもしれません。
70 <classname>Zend_Acl</classname> では、このような状況も簡単に処理できます。
71 例外的な規則を適用する建物については、建物に対して直接規則を定義すればいいのです。
72 リソースは、単一のリソースしか継承することができません。
73 そしてその継承元のリソースがまた別の親リソースを継承し……
77 <classname>Zend_Acl</classname> は、リソースに対する権限 ("create"、"read"、"update"、"delete" など)
78 もサポートしており、すべての権限あるいは一部の権限に影響を及ぼす規則を、
83 <sect2 id="zend.acl.introduction.roles">
86 リソースと同様、ロールを作成するのも簡単です。Zend_Acl の
87 <classname>Zend_Acl_Role_Interface</classname> に、
88 開発者がロールを作成するの手助けする機能が含まれています。
89 ロールクラスは、単にこのインターフェイスを実装するだけで作成できます。
90 このインターフェイスに含まれるメソッドはひとつだけで、それは
91 <methodname>getRoleId()</methodname> です。このメソッドにより、
92 Zend_Acl はそのオブジェクトがロールであると判断します。さらに、
93 基本的なロールの実装を含む <classname>Zend_Acl_Role</classname>
94 が <classname>Zend_Acl</classname> にインクルードされています。
95 開発者は、必要な部分だけを拡張することでリソースを作成できます。
98 <classname>Zend_Acl</classname> では、あるロールは他の複数のロールを継承できます。
99 これは、それぞれのロールの規則を継承することをサポートするためのものです。
100 たとえば、"sally" のようなユーザロールは、"editor" かつ "administrator"
101 のように複数の親ロールに属することもありえるでしょう。
102 この場合、開発者は "editor" および "administrator" にそれぞれ別に規則を定義します。
103 そして "sally" がその両方を継承することにします。
104 "sally" に規則を直接定義する必要はありません。
107 複数のロールからの継承は非常に便利ですが、
108 多重継承は複雑な問題を引き起こすこともあります。
109 次の例は、あいまいな条件になったときに <classname>Zend_Acl</classname>
112 <example id="zend.acl.introduction.roles.example.multiple_inheritance">
113 <title>ロールの多重継承</title>
115 以下のコードでは、基本となる三つのロール "guest"、"member"
116 および "admin" を定義しています。他のロールはこれらを継承することになります。
117 次に、"someUser" というロールを作成してこれらの三つのロールを継承します。
118 これらのロールが配列 <code>$parents</code> にあらわれる順序が重要となります。
119 問い合わせ先のロール (ここでは "someUser" にアクセス規則が定義されていないが
120 その継承元 (ここでは "guest"、"member" および "admin")
121 には定義されているという場合、<classname>Zend_Acl</classname> はそちらを検索します。
123 <programlisting language="php"><![CDATA[
124 $acl = new Zend_Acl();
126 $acl->addRole(new Zend_Acl_Role('guest'))
127 ->addRole(new Zend_Acl_Role('member'))
128 ->addRole(new Zend_Acl_Role('admin'));
130 $parents = array('guest', 'member', 'admin');
131 $acl->addRole(new Zend_Acl_Role('someUser'), $parents);
133 $acl->add(new Zend_Acl_Resource('someResource'));
135 $acl->deny('guest', 'someResource');
136 $acl->allow('member', 'someResource');
138 echo $acl->isAllowed('someUser', 'someResource') ? 'allowed' : 'denied';
142 "someResource" に対する規則は定義されていないので、
143 <classname>Zend_Acl</classname> は、その規則が "someUser"
144 の継承元ロールで定義されているものとして検索します。
145 まず "admin" ロールを探しますが、ここではアクセス規則が定義されていません。
146 次に "member" ロールを探し、ここで <classname>Zend_Acl</classname> が規則を発見します。つまり
147 "member" は "someResource" へのアクセスを許可されているということです。
150 しかし、仮に <classname>Zend_Acl</classname> がさらに別の親に対しても規則の検索を続けたとすると、
151 "guest" は "someResource" へのアクセスが拒否されていることに気づくことでしょう。
152 これは問題となります。というのも、"someUser" は
153 "someResource" へのアクセスが許可されていると同時に拒否されているわけで、
154 それぞれ別の親ロールから取得した規則が衝突することになるからです。
157 <classname>Zend_Acl</classname> では、このような衝突の可能性を解決するために、
158 直近に継承されたロールの優先度が高くなるようにしています。
160 "guest" ロールより先に調べられ、例のコードの出力は
166 複数の親をロールに指定する場合は、承認クエリでの規則の検索順を覚えておきましょう。
172 <sect2 id="zend.acl.introduction.creating">
173 <title>アクセス制御リストの作成</title>
176 アクセス制御リスト (<acronym>ACL</acronym>) を使用して、物理的あるいは仮想的なオブジェクトの組み合わせを
177 お望みどおりに表現できます。しかしここでは、説明用として、
178 基本的なコンテンツ管理システム (<acronym>CMS</acronym>) の <acronym>ACL</acronym> を考えます。
179 これは、さまざまな領域で複数階層のグループを管理するものです。
180 新しい <acronym>ACL</acronym> オブジェクトを作成するには、何もパラメータを指定せずに
181 <acronym>ACL</acronym> のインスタンスを作成します。
184 <programlisting language="php"><![CDATA[
185 $acl = new Zend_Acl();
190 開発者が "allow" 規則を指定しない限り、<classname>Zend_Acl</classname>
191 はあらゆるロールのすべてのリソース上の権限からのアクセスも拒否します。
196 <sect2 id="zend.acl.introduction.role_registry">
197 <title>ロールの登録</title>
200 コンテンツ管理システムでは、ほとんどすべての場面で権限階層の管理が必要となります。
201 これにより、ユーザの編集権限を決定します。たとえば 'Guest'
202 グループに対してはデモ用に限定したアクセス権限のみを許可し、
203 'Staff' グループは通常の操作をする大半の <acronym>CMS</acronym> ユーザ用に作成し、
204 'Editor' グループにはコンテンツの公開やレビュー、保存や削除の権限を与え、
205 最後に 'Administrator' は、その他のすべてのグループの権限に加えて
206 機密情報の管理やユーザ管理、バックエンドの設定データ、
207 バックアップ、そしてエクスポート機能を与えるといったようになります。
208 これらの権限を、ロールレジストリで表すことができます。
209 各グループの権限を '親の' グループから継承させ、
210 そのグループに固有の権限を追加で定義します。
211 これらの権限を整理すると、次のようになります。
214 <table id="zend.acl.introduction.role_registry.table.example_cms_access_controls">
215 <title>サンプル CMS 用のアクセス制御</title>
221 <entry>継承する権限の継承元</entry>
232 <entry>Edit, Submit, Revise</entry>
236 <entry>Editor</entry>
237 <entry>Publish, Archive, Delete</entry>
241 <entry>Administrator</entry>
242 <entry>(すべてのアクセスを許可)</entry>
250 この例では <classname>Zend_Acl_Role</classname> を用いていますが、
251 <classname>Zend_Acl_Role_Interface</classname> を実装しているオブジェクトなら何でも使用可能です。
252 これらのグループを、次のようにしてロールレジストリに追加します。
255 <programlisting language="php"><![CDATA[
256 $acl = new Zend_Acl();
258 // Zend_Acl_Role を使用して、グループをロールレジストリに追加します
259 // Guest はアクセス制御を受け継ぎません
260 $roleGuest = new Zend_Acl_Role('guest');
261 $acl->addRole($roleGuest);
263 // Staff は guest の権限を継承します
264 $acl->addRole(new Zend_Acl_Role('staff'), $roleGuest);
267 あるいは、上の内容は次のように書くこともできます
268 $acl->addRole(new Zend_Acl_Role('staff'), 'guest');
271 // Editor は staff の権限を継承します
272 $acl->addRole(new Zend_Acl_Role('editor'), 'staff');
274 // Administrator はアクセス制御を受け継ぎません
275 $acl->addRole(new Zend_Acl_Role('administrator'));
280 <sect2 id="zend.acl.introduction.defining">
281 <title>アクセス制御の定義</title>
284 <acronym>ACL</acronym> に適切なロールが含まれた状態になりました。これで、リソースに対して
285 ロールがどのようにアクセスするのかという規則を定義できる状態になりました。
286 この例では特定のリソースを定義していないことにお気づきかもしれません。
287 この場合、規則はすべてのリソースに対して適用されます。
288 <classname>Zend_Acl</classname> を使用すると、全般的なものであろうが特殊なものであろうが
289 規則を適用するだけで定義できるようになります。
290 リソースやロールは、その継承元で定義されている規則を引き継ぐからです。
295 一般に、<classname>Zend_Acl</classname> は指定された規則に従います。
296 ただし、より詳細な規則が別途適用されている場合は例外です。
301 そのため、複雑な規則の組み合わせを最小限のコードで定義できるようになります。
302 上で定義した基本的な権限を適用するには、次のようにします。
305 <programlisting language="php"><![CDATA[
306 $acl = new Zend_Acl();
308 $roleGuest = new Zend_Acl_Role('guest');
309 $acl->addRole($roleGuest);
310 $acl->addRole(new Zend_Acl_Role('staff'), $roleGuest);
311 $acl->addRole(new Zend_Acl_Role('editor'), 'staff');
312 $acl->addRole(new Zend_Acl_Role('administrator'));
314 // Guest は、コンテンツを閲覧することのみが可能です
315 $acl->allow($roleGuest, null, 'view');
318 上と同じ内容を、このように書くこともできます
319 $acl->allow('guest', null, 'view');
322 // Staff は guest の権限をすべて引き継いだうえで、さらに追加の権限を必要とします
323 $acl->allow('staff', null, array('edit', 'submit', 'revise'));
325 // Editor は、staff の権限 (view、edit、submit および revise)
326 // を引き継いだうえで、さらに追加の権限を必要とします
327 $acl->allow('editor', null, array('publish', 'archive', 'delete'));
329 // Administrator は何も引き継ぎませんが、すべての権限が認められています
330 $acl->allow('administrator');
334 上の <methodname>allow()</methodname> のコールにおける <constant>NULL</constant> は、
335 規則をすべてのリソースに対して適用することを意味します。
340 <sect2 id="zend.acl.introduction.querying">
341 <title>ACL への問い合わせ</title>
344 これで、柔軟な <acronym>ACL</acronym> が作成できました。これにより、
346 ある機能を使用するために必要な権限を持っているかを調べられるようになりました。
347 問い合わせを行うのは簡単で、単に <methodname>isAllowed()</methodname>
351 <programlisting language="php"><![CDATA[
352 echo $acl->isAllowed('guest', null, 'view') ?
353 "allowed" : "denied";
356 echo $acl->isAllowed('staff', null, 'publish') ?
357 "allowed" : "denied";
360 echo $acl->isAllowed('staff', null, 'revise') ?
361 "allowed" : "denied";
364 echo $acl->isAllowed('editor', null, 'view') ?
365 "allowed" : "denied";
366 // guest から引き継いでいるので allowed となります
368 echo $acl->isAllowed('editor', null, 'update') ?
369 "allowed" : "denied";
370 // 'update' 用の規則がないので denied となります
372 echo $acl->isAllowed('administrator', null, 'view') ?
373 "allowed" : "denied";
374 // administrator はすべての権限が許可されているので allowed となります
376 echo $acl->isAllowed('administrator') ?
377 "allowed" : "denied";
378 // administrator はすべての権限が許可されているので allowed となります
380 echo $acl->isAllowed('administrator', null, 'update') ?
381 "allowed" : "denied";
382 // administrator はすべての権限が許可されているので allowed となります