Zend_Acl.xml 16 KB

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