Zend_Acl.xml 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- Reviewed: no -->
  3. <sect1 id="zend.acl.introduction">
  4. <title>Introduction</title>
  5. <para>
  6. <classname>Zend_Acl</classname> provides a lightweight and flexible access control list
  7. (ACL) implementation for privileges management. In general, an application may utilize such
  8. ACL's to control access to certain protected objects by other requesting objects.
  9. </para>
  10. <para>
  11. For the purposes of this documentation,
  12. <itemizedlist>
  13. <listitem>
  14. <para>
  15. a <emphasis role="strong">resource</emphasis> is an object
  16. to which access is controlled.
  17. </para>
  18. </listitem>
  19. <listitem>
  20. <para>
  21. a <emphasis role="strong">role</emphasis> is an object
  22. that may request access to a Resource.
  23. </para>
  24. </listitem>
  25. </itemizedlist>
  26. Put simply, <emphasis role="strong">roles request access to resources</emphasis>. For
  27. example, if a parking attendant requests access to a car, then the parking attendant is the
  28. requesting role, and the car is the resource, since access to the car may not be granted to
  29. everyone.
  30. </para>
  31. <para>
  32. Through the specification and use of an ACL, an application may control how roles are
  33. granted access to resources.
  34. </para>
  35. <sect2 id="zend.acl.introduction.resources">
  36. <title>Resources</title>
  37. <para>
  38. Creating a resource in <classname>Zend_Acl</classname> is very simple.
  39. <classname>Zend_Acl</classname> provides the resource,
  40. <classname>Zend_Acl_Resource_Interface</classname>, to facilitate creating resources in
  41. an application. A class need only implement this interface, which consists of a single
  42. method, <code>getResourceId()</code>, so <classname>Zend_Acl</classname> to recognize
  43. the object as a resource. Additionally, <classname>Zend_Acl_Resource</classname> is
  44. provided by <classname>Zend_Acl</classname> as a basic resource implementation for
  45. developers to extend as needed.
  46. </para>
  47. <para>
  48. <classname>Zend_Acl</classname> provides a tree structure to which multiple resources
  49. can be added. Since resources are stored in such a tree structure, they can be
  50. organized from the general (toward the tree root) to the specific (toward the tree
  51. leaves). Queries on a specific resource will automatically search the resource's
  52. hierarchy for rules assigned to ancestor resources, allowing for simple inheritance of
  53. rules. For example, if a default rule is to be applied to each building in a city, one
  54. would simply assign the rule to the city, instead of assigning the same rule to each
  55. building. Some buildings may require exceptions to such a rule, however, and this can
  56. be achieved in <classname>Zend_Acl</classname> by assigning such exception rules to
  57. each building that requires such an exception. A resource may inherit from only one
  58. parent resource, though this parent resource can have its own parent resource, etc.
  59. </para>
  60. <para>
  61. <classname>Zend_Acl</classname> also supports privileges on resources (e.g., "create",
  62. "read", "update", "delete"), so the developer can assign rules that affect all
  63. privileges or specific privileges on one or more resources.
  64. </para>
  65. </sect2>
  66. <sect2 id="zend.acl.introduction.roles">
  67. <title>Roles</title>
  68. <para>
  69. As with resources, creating a role is also very simple. All roles must implement
  70. <classname>Zend_Acl_Role_Interface</classname>. This interface consists of a single
  71. method, <code>getRoleId()</code>, Additionally, <classname>Zend_Acl_Role</classname> is
  72. provided by <classname>Zend_Acl</classname> as a basic role implementation for
  73. developers to extend as needed.
  74. </para>
  75. <para>
  76. In <classname>Zend_Acl</classname>, a role may inherit from one or more roles. This is
  77. to support inheritance of rules among roles. For example, a user role, such as "sally",
  78. may belong to one or more parent roles, such as "editor" and "administrator". The
  79. developer can assign rules to "editor" and "administrator" separately, and "sally"
  80. would inherit such rules from both, without having to assign rules directly to "sally".
  81. </para>
  82. <para>
  83. Though the ability to inherit from multiple roles is very useful, multiple inheritance
  84. also introduces some degree of complexity. The following example illustrates the
  85. ambiguity condition and how <classname>Zend_Acl</classname> solves it.
  86. </para>
  87. <example id="zend.acl.introduction.roles.example.multiple_inheritance">
  88. <title>Multiple Inheritance among Roles</title>
  89. <para>
  90. The following code defines three base roles - "<code>guest</code>",
  91. "<code>member</code>", and "<code>admin</code>" - from which other roles may
  92. inherit. Then, a role identified by "<code>someUser</code>" is established and
  93. inherits from the three other roles. The order in which these roles appear in the
  94. <code>$parents</code> array is important. When necessary,
  95. <classname>Zend_Acl</classname> searches for access rules defined not only for the
  96. queried role (herein, "<code>someUser</code>"), but also upon the roles from which
  97. the queried role inherits (herein, "<code>guest</code>", "<code>member</code>", and
  98. "<code>admin</code>"):
  99. </para>
  100. <programlisting role="php"><![CDATA[
  101. $acl = new Zend_Acl();
  102. $acl->addRole(new Zend_Acl_Role('guest'))
  103. ->addRole(new Zend_Acl_Role('member'))
  104. ->addRole(new Zend_Acl_Role('admin'));
  105. $parents = array('guest', 'member', 'admin');
  106. $acl->addRole(new Zend_Acl_Role('someUser'), $parents);
  107. $acl->add(new Zend_Acl_Resource('someResource'));
  108. $acl->deny('guest', 'someResource');
  109. $acl->allow('member', 'someResource');
  110. echo $acl->isAllowed('someUser', 'someResource') ? 'allowed' : 'denied';
  111. ]]></programlisting>
  112. <para>
  113. Since there is no rule specifically defined for the "someUser" role and
  114. "someResource", <classname>Zend_Acl</classname> must search for rules that may be
  115. defined for roles that "someUser" inherits. First, the "admin" role is visited, and
  116. there is no access rule defined for it. Next, the "member" role is visited, and
  117. <classname>Zend_Acl</classname> finds that there is a rule specifying that "member"
  118. is allowed access to "someResource".
  119. </para>
  120. <para>
  121. If <classname>Zend_Acl</classname> were to continue examining the rules defined for
  122. other parent roles, however, it would find that "guest" is denied access to
  123. "<code>someResource</code>". This fact introduces an ambiguity because now
  124. "someUser" is both denied and allowed access to "someResource", by reason of having
  125. inherited conflicting rules from different parent roles.
  126. </para>
  127. <para>
  128. <classname>Zend_Acl</classname> resolves this ambiguity by completing a query when
  129. it finds the first rule that is directly applicable to the query. In this case,
  130. since the "member" role is examined before the "guest" role, the example code would
  131. print "<code>allowed</code>".
  132. </para>
  133. </example>
  134. <note>
  135. <para>
  136. When specifying multiple parents for a role, keep in mind that the last parent
  137. listed is the first one searched for rules applicable to an authorization query.
  138. </para>
  139. </note>
  140. </sect2>
  141. <sect2 id="zend.acl.introduction.creating">
  142. <title>Creating the Access Control List</title>
  143. <para>
  144. An Access Control List (ACL) can represent any set of physical or virtual objects that
  145. you wish. For the purposes of demonstration, however, we will create a basic Content
  146. Management System (CMS) ACL that maintains several tiers of groups over a wide variety
  147. of areas. To create a new ACL object, we instantiate the ACL with no parameters:
  148. </para>
  149. <programlisting role="php"><![CDATA[
  150. $acl = new Zend_Acl();
  151. ]]></programlisting>
  152. <note>
  153. <para>
  154. Until a developer specifies an "allow" rule, <classname>Zend_Acl</classname> denies
  155. access to every privilege upon every resource by every role.
  156. </para>
  157. </note>
  158. </sect2>
  159. <sect2 id="zend.acl.introduction.role_registry">
  160. <title>Registering Roles</title>
  161. <para>
  162. CMS's will nearly always require a hierarchy of permissions to determine the authoring
  163. capabilities of its users. There may be a 'Guest' group to allow limited access for
  164. demonstrations, a 'Staff' group for the majority of CMS users who perform most of the
  165. day-to-day operations, an 'Editor' group for those responsible for publishing,
  166. reviewing, archiving and deleting content, and finally an 'Administrator' group whose
  167. tasks may include all of those of the other groups as well as maintenance of sensitive
  168. information, user management, back-end configuration data and backup/export. This set
  169. of permissions can be represented in a role registry, allowing each group to inherit
  170. privileges from 'parent' groups, as well as providing distinct privileges for their
  171. unique group only. The permissions may be expressed as follows:
  172. </para>
  173. <table id="zend.acl.introduction.role_registry.table.example_cms_access_controls">
  174. <title>Access Controls for an Example CMS</title>
  175. <tgroup cols="3">
  176. <thead>
  177. <row>
  178. <entry>Name</entry>
  179. <entry>Unique Permissions</entry>
  180. <entry>Inherit Permissions From</entry>
  181. </row>
  182. </thead>
  183. <tbody>
  184. <row>
  185. <entry>Guest</entry>
  186. <entry>View</entry>
  187. <entry>N/A</entry>
  188. </row>
  189. <row>
  190. <entry>Staff</entry>
  191. <entry>Edit, Submit, Revise</entry>
  192. <entry>Guest</entry>
  193. </row>
  194. <row>
  195. <entry>Editor</entry>
  196. <entry>Publish, Archive, Delete</entry>
  197. <entry>Staff</entry>
  198. </row>
  199. <row>
  200. <entry>Administrator</entry>
  201. <entry>(Granted all access)</entry>
  202. <entry>N/A</entry>
  203. </row>
  204. </tbody>
  205. </tgroup>
  206. </table>
  207. <para>
  208. For this example, <classname>Zend_Acl_Role</classname> is used, but any object that
  209. implements <classname>Zend_Acl_Role_Interface</classname> is acceptable. These groups
  210. can be added to the role registry as follows:
  211. </para>
  212. <programlisting role="php"><![CDATA[
  213. $acl = new Zend_Acl();
  214. // Add groups to the Role registry using Zend_Acl_Role
  215. // Guest does not inherit access controls
  216. $roleGuest = new Zend_Acl_Role('guest');
  217. $acl->addRole($roleGuest);
  218. // Staff inherits from guest
  219. $acl->addRole(new Zend_Acl_Role('staff'), $roleGuest);
  220. /*
  221. Alternatively, the above could be written:
  222. $acl->addRole(new Zend_Acl_Role('staff'), 'guest');
  223. */
  224. // Editor inherits from staff
  225. $acl->addRole(new Zend_Acl_Role('editor'), 'staff');
  226. // Administrator does not inherit access controls
  227. $acl->addRole(new Zend_Acl_Role('administrator'));
  228. ]]></programlisting>
  229. </sect2>
  230. <sect2 id="zend.acl.introduction.defining">
  231. <title>Defining Access Controls</title>
  232. <para>
  233. Now that the ACL contains the relevant roles, rules can be established that define how
  234. resources may be accessed by roles. You may have noticed that we have not defined any
  235. particular resources for this example, which is simplified to illustrate that the rules
  236. apply to all resources. <classname>Zend_Acl</classname> provides an implementation
  237. whereby rules need only be assigned from general to specific, minimizing the number of
  238. rules needed, because resources and roles inherit rules that are defined upon their
  239. ancestors.
  240. </para>
  241. <note>
  242. <para>
  243. In general, <classname>Zend_Acl</classname> obeys a given rule if and only if a
  244. more specific rule does not apply.
  245. </para>
  246. </note>
  247. <para>
  248. Consequently, we can define a reasonably complex set of rules with a minimum amount of
  249. code. To apply the base permissions as defined above:
  250. </para>
  251. <programlisting role="php"><![CDATA[
  252. $acl = new Zend_Acl();
  253. $roleGuest = new Zend_Acl_Role('guest');
  254. $acl->addRole($roleGuest);
  255. $acl->addRole(new Zend_Acl_Role('staff'), $roleGuest);
  256. $acl->addRole(new Zend_Acl_Role('editor'), 'staff');
  257. $acl->addRole(new Zend_Acl_Role('administrator'));
  258. // Guest may only view content
  259. $acl->allow($roleGuest, null, 'view');
  260. /*
  261. Alternatively, the above could be written:
  262. $acl->allow('guest', null, 'view');
  263. //*/
  264. // Staff inherits view privilege from guest, but also needs additional
  265. // privileges
  266. $acl->allow('staff', null, array('edit', 'submit', 'revise'));
  267. // Editor inherits view, edit, submit, and revise privileges from
  268. // staff, but also needs additional privileges
  269. $acl->allow('editor', null, array('publish', 'archive', 'delete'));
  270. // Administrator inherits nothing, but is allowed all privileges
  271. $acl->allow('administrator');
  272. ]]></programlisting>
  273. <para>
  274. The <code>null</code> values in the above <code>allow()</code> calls are used to
  275. indicate that the allow rules apply to all resources.
  276. </para>
  277. </sect2>
  278. <sect2 id="zend.acl.introduction.querying">
  279. <title>Querying an ACL</title>
  280. <para>
  281. We now have a flexible ACL that can be used to determine whether requesters have
  282. permission to perform functions throughout the web application. Performing queries is
  283. quite simple using the <code>isAllowed()</code> method:
  284. </para>
  285. <programlisting role="php"><![CDATA[
  286. echo $acl->isAllowed('guest', null, 'view') ?
  287. "allowed" : "denied";
  288. // allowed
  289. echo $acl->isAllowed('staff', null, 'publish') ?
  290. "allowed" : "denied";
  291. // denied
  292. echo $acl->isAllowed('staff', null, 'revise') ?
  293. "allowed" : "denied";
  294. // allowed
  295. echo $acl->isAllowed('editor', null, 'view') ?
  296. "allowed" : "denied";
  297. // allowed because of inheritance from guest
  298. echo $acl->isAllowed('editor', null, 'update') ?
  299. "allowed" : "denied";
  300. // denied because no allow rule for 'update'
  301. echo $acl->isAllowed('administrator', null, 'view') ?
  302. "allowed" : "denied";
  303. // allowed because administrator is allowed all privileges
  304. echo $acl->isAllowed('administrator') ?
  305. "allowed" : "denied";
  306. // allowed because administrator is allowed all privileges
  307. echo $acl->isAllowed('administrator', null, 'update') ?
  308. "allowed" : "denied";
  309. // allowed because administrator is allowed all privileges
  310. ]]></programlisting>
  311. </sect2>
  312. </sect1>
  313. <!--
  314. vim:se ts=4 sw=4 et:
  315. -->