Zend_Acl.xml 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. <sect1 id="zend.acl.introduction">
  2. <title>Wprowadzenie</title>
  3. <para>
  4. Zend_Acl zapewnia lekką i elastyczną obsługę implementacji list
  5. kontroli dostępu (ACL) do zarządzania uprawnieniami. Ogólnie rzecz
  6. biorąc, aplikacja może używać list ACL do kontrolowania
  7. dostępu do określonych chronionych obiektów przez inne obiekty.
  8. </para>
  9. <para>
  10. Dla celów tej dokumentacji,
  11. <itemizedlist>
  12. <listitem>
  13. <para>
  14. <emphasis role="strong">zasób</emphasis> jest obiektem do
  15. którego dostęp jest kontrolowany.
  16. </para>
  17. </listitem>
  18. <listitem>
  19. <para>
  20. <emphasis role="strong">rola</emphasis> jest obiektem, który
  21. może zażądać dostępu do zasobu.
  22. </para>
  23. </listitem>
  24. </itemizedlist>
  25. Przystępnie mówiąc, <emphasis role="strong">role żądają dostępu do zasobów</emphasis>.
  26. Na przykład, jeśli obsługujący parking samochodow zażąda dostępu do
  27. samochodu, to ta osoba jest rolą, a samochód jest zasobem, więc dostęp
  28. do samochodu nie musi zostać przyznany każdemu.
  29. </para>
  30. <para>
  31. Dzięki określeniu i użyciu list kontroli dostępu (ACL), aplikacja może
  32. kontrolować to, w jaki sposób żądające obiekty (role) mają przydzielany
  33. dostęp do chronionych obiektów (zasobów).
  34. </para>
  35. <sect2 id="zend.acl.introduction.resources">
  36. <title>O zasobach</title>
  37. <para>
  38. Tworzenie zasobu w Zend_Acl jest bardzo proste. Zend_Acl zapewnia
  39. interfejs <code>Zend_Acl_Resource_Interface</code> aby ułatwić
  40. programistom tworzenie zasobów w aplikacji. Klasa jedynie implementuje ten
  41. interfejs, który składa się z jednej metody, <code>getResourceId()</code>,
  42. dzięki ktorej Zend_Acl wie, że obiekt jest zasobem. Dodatkowo w
  43. Zend_Acl dołączona jest klasa <code>Zend_Acl_Resource</code>,
  44. która jest podstawową implementacją zasobu do użycia przez
  45. programistów gdy jest to potrzebne.
  46. </para>
  47. <para>
  48. Zend_Acl zapewnia drzewiastą strukturę, w której mogą być dodawane
  49. zasoby (lub inaczej "obszary będące pod kontrolą"). Dzięki temu, że
  50. zasoby są przechowywane w strukturze drzewiastej, mogą być one
  51. organizowane od ogólnych (od korzeni) do szczegółowych (do gałęzi).
  52. Zapytanie do konkretnego zasobu automatycznie przeszuka całą
  53. hierarchię zasobów, dla reguł przypisanych do przodka zasobów,
  54. pozwalając na proste dziedziczenie reguł. Na przykład, jeśli
  55. domyślna reguła ma być zastosowana do każdego budynku w mieście,
  56. wystarczy przypisać regułę do miasta, zamiast przypisywać regułę to
  57. każdego z budynków z osobna. Niektóre z budynków mogą wymagać
  58. wyjątków od tej reguły i może być to osiągnięte w łatwy sposób w
  59. Zend_Acl poprzez przypisanie takiej wyjątkowej reguły dla każdego z
  60. budynków wymagających wyjątku. Zasób może dziedziczyć tylko od
  61. jednego zasobu rodzica, a ten rodzic może także dziedziczyć tylko od
  62. jednego zasobu itd.
  63. </para>
  64. <para>
  65. Zend_Acl także obsługuje przywileje dla zasobów (np., "create",
  66. "read", "update", "delete") i programista może przypisać reguły,
  67. które mają zastosowanie do wszystkich przywilejów, lub dla
  68. konkretnych przywilejów dla jednego lub więcej zasobów.
  69. </para>
  70. </sect2>
  71. <sect2 id="zend.acl.introduction.roles">
  72. <title>O rolach</title>
  73. <para>
  74. Tak jak tworzenie zasobów, tworzenie ról także jest bardzo proste.
  75. Wszystkie role muszą implementować interfejs <code>Zend_Acl_Role_Interface</code>
  76. Ten interfejs składa się z jednej metody, <code>getRoleId()</code>,
  77. dzięki ktorej Zend_Acl wie, że obiekt jest rolą. Dodatkowo w
  78. Zend_Acl dołączona jest klasa <code>Zend_Acl_Role</code>,
  79. która jest podstawową implementacją roli do użycia przez
  80. programistów gdy jest to potrzebne.
  81. </para>
  82. <para>
  83. W Zend_Acl rola może dziedziczyć z jednej lub więcej ról. Jest to po
  84. to, aby możliwe było dziedziczenie zasad dla ról. Na przykład rola,
  85. użytkownik "sally", może dziedziczyć z jednej lub więcej ról
  86. rodziców, takich jak na przykład "editor" oraz "administrator".
  87. Programista może przypisać reguły dla ról "editor" oraz
  88. "administrator" osobno, a "sally" będzie dziedziczyć te reguły od
  89. obu ról, bez konieczności przypisania reguł bezpośrednio dla
  90. "sally".
  91. </para>
  92. <para>
  93. Chociaż możliwość dziedziczenia po wielu rolach jest bardzo
  94. użyteczna, to takie dziedziczenie wprowadza pewien stopień
  95. złożoności. Poniższy przykład ilustruje niejasny przypadek
  96. dziedziczenia i pokazuje w jaki sposób Zend_Acl go rozwiązuje.
  97. </para>
  98. <example id="zend.acl.introduction.roles.example.multiple_inheritance">
  99. <title>Dziedziczenie po wielu rolach</title>
  100. <para>
  101. Poniższy kod definiuje trzy podstawowe role, po których inne role
  102. mogą dziedziczyć - "<code>guest</code>", "<code>member</code>",
  103. oraz "<code>admin</code>". Następnie definiowana jest rola o
  104. nazwie "<code>someUser</code>", ktora dziedziczy po zdefiniowanych
  105. wcześniej trzech rolach. Ważna jest kolejność zdefiniowania tych
  106. trzech ról w tablicy <code>$parents</code>. Gdy sprawdzamy
  107. reguły dostępu, Zend_Acl szuka reguł zdefiniowanych nie tylko dla
  108. danej roli (w tym przypadku "<code>someUser</code>"), ale także
  109. dla ról, po których ta rola dziedziczy (w tym przypadku
  110. "<code>guest</code>", "<code>member</code>" oraz "<code>admin</code>"):
  111. </para>
  112. <programlisting role="php"><![CDATA[
  113. $acl = new Zend_Acl();
  114. $acl->addRole(new Zend_Acl_Role('guest'))
  115. ->addRole(new Zend_Acl_Role('member'))
  116. ->addRole(new Zend_Acl_Role('admin'));
  117. $parents = array('guest', 'member', 'admin');
  118. $acl->addRole(new Zend_Acl_Role('someUser'), $parents);
  119. $acl->add(new Zend_Acl_Resource('someResource'));
  120. $acl->deny('guest', 'someResource');
  121. $acl->allow('member', 'someResource');
  122. echo $acl->isAllowed('someUser', 'someResource') ? 'allowed' : 'denied';
  123. ]]>
  124. </programlisting>
  125. <para>
  126. Z tego względu, że nie ma zdefiniowanych reguł konkretnie dla
  127. roli "<code>someUser</code>" oraz dla zasobu "<code>someResource</code>",
  128. Zend_Acl musi szukać zasad, ktore mogą być zdefiniowane dla ról,
  129. po których dziedziczy rola "<code>someUser</code>". Wpierw
  130. sprawdzana jest rola "<code>admin</code>", a dla niej nie ma
  131. zdefiniowanej żadnej reguły dostępu. Następnie sprawdzana jest
  132. rola "<code>member</code>" i Zend_Acl znajduje zdefiniowaną
  133. regułę zezwalająca roli "<code>member</code>" na dostęp do zasobu
  134. "<code>someResource</code>".
  135. </para>
  136. <para>
  137. Jeśli Zend_Acl kontynuowałby sprawdzanie reguł zdefiniowanych dla
  138. innych ról rodziców, znalazłby regułę zabraniającą roli
  139. "<code>guest</code>" dostępu do zasobu "<code>someResource</code>".
  140. Ten fakt wprowadza niejaność, ponieważ teraz rola
  141. "<code>someUser</code>" ma zarówno dozwolony jak i zabroniony
  142. dostęp do zasobu "<code>someResource</code>", z tego powodu, że
  143. posiada odziedziczone po dwóch rolach reguły, które są ze sobą
  144. sprzeczne.
  145. </para>
  146. <para>
  147. Zend_Acl rozwiązuje tę niejaśność kończąc zapytanie wtedy, gdy
  148. znajdzie pierwszą regułę, wprost pasującą do zapytania. W tym
  149. przypadku, z tego względu, że rola "<code>member</code>" jest
  150. sprawdzana przed rolą "<code>guest</code>", przykładowy kod
  151. wyświetliłby "<code>allowed</code>".
  152. </para>
  153. </example>
  154. <note>
  155. <para>
  156. Gdy określasz wielu rodziców dla roli, pamiętaj, że ostatni
  157. rodzic na liście jest pierwszym przeszukiwanym rodzicem w
  158. celu znalezienia ról pasujących do zapytania autoryzacyjnego.
  159. </para>
  160. </note>
  161. </sect2>
  162. <sect2 id="zend.acl.introduction.creating">
  163. <title>Tworzenie list kontroli dostępu (ACL)</title>
  164. <para>
  165. ACL może reprezentować dowolny zestaw fizycznych lub wirtualnych
  166. obiektów których potrzebujesz. Dla celów prezentacji utworzymy ACL
  167. dla prostego Systemu Zarządzania Treścią (Content Management System
  168. - CMS), w którym różnymi obszarami zarządza kilka poziomów grup.
  169. Aby utworzyć nowy obiekt ACL, utwórzmy instancję ACL bez parametrów:
  170. </para>
  171. <programlisting role="php"><![CDATA[
  172. $acl = new Zend_Acl();
  173. ]]>
  174. </programlisting>
  175. <note>
  176. <para>
  177. Dopóki programista nie określi reguły "allow", Zend_Acl zabroni
  178. dostępu wszystkim rolom do wszystkich przywilejów dla wszystkich
  179. zasobów.
  180. </para>
  181. </note>
  182. </sect2>
  183. <sect2 id="zend.acl.introduction.role_registry">
  184. <title>Rejestrowanie ról</title>
  185. <para>
  186. System Zarządzania Treścią prawie zawsze potrzebuje hierarchii
  187. uprawnień aby określić możliwości jego użytkowników.
  188. Może być tu grupa 'Guest' aby pozwolić na limitowany dostęp
  189. dla celów demonstracyjnych, grupa 'Staff' dla większości
  190. użytkowników aplikacji CMS, którzy przeprowadzają najczęstsze
  191. codzienne operacje, grupa 'Editor' dla tych odpowiedzialnych za
  192. publikowanie, przeglądanie, archiwizowanie i usuwanie zawartości i
  193. ostatecznie grupa 'Administrator', której zadania obejmują zarówno
  194. zadania wszystkich innych grup, jak i zarządzanie ważnymi
  195. informacjami, zarządzanie użytkownikami, konfigurację baz danych
  196. oraz przeprowadzanie kopii zapasowych/eksportu danych.
  197. Ten zestaw pozwoleń może być reprezentowany w rejestrze ról,
  198. pozwalając każdej grupie dziedziczyć uprawnienia z grup rodziców,
  199. a także umożliwiając każdej z grup posiadanie własnych unikalnych
  200. uprawnień. Uprawnienia mogą być wyrażone w taki sposób:
  201. </para>
  202. <table id="zend.acl.introduction.role_registry.table.example_cms_access_controls">
  203. <title>Kontrola dostępu dla przykładowego CMS</title>
  204. <tgroup cols="3">
  205. <thead>
  206. <row>
  207. <entry>Nazwa</entry>
  208. <entry>Unikalne uprawnienia</entry>
  209. <entry>Dzidziczy uprawnienia od</entry>
  210. </row>
  211. </thead>
  212. <tbody>
  213. <row>
  214. <entry>Guest</entry>
  215. <entry>View</entry>
  216. <entry>N/A</entry>
  217. </row>
  218. <row>
  219. <entry>Staff</entry>
  220. <entry>Edit, Submit, Revise</entry>
  221. <entry>Guest</entry>
  222. </row>
  223. <row>
  224. <entry>Editor</entry>
  225. <entry>Publish, Archive, Delete</entry>
  226. <entry>Staff</entry>
  227. </row>
  228. <row>
  229. <entry>Administrator</entry>
  230. <entry>(posiada cały dostęp)</entry>
  231. <entry>N/A</entry>
  232. </row>
  233. </tbody>
  234. </tgroup>
  235. </table>
  236. <para>
  237. W tym przykładzie użyty jest obiekt <code>Zend_Acl_Role</code>, ale
  238. dozwolony jest dowolny obiekt, który implementuje interfejs
  239. <code>Zend_Acl_Role_Interface</code>. Te grupy mogą być dodane
  240. do rejestru ról w taki sposób:
  241. </para>
  242. <programlisting role="php"><![CDATA[
  243. $acl = new Zend_Acl();
  244. // Dodajemy grupy do rejestru ról używając obiektu Zend_Acl_Role
  245. // Grupa guest nie dziedziczy kontroli dostępu
  246. $roleGuest = new Zend_Acl_Role('guest');
  247. $acl->addRole($roleGuest);
  248. // Grupa staff dzidziczy od grupy guest
  249. $acl->addRole(new Zend_Acl_Role('staff'), $roleGuest);
  250. /*
  251. alternatywnie, powyższe mogłoby wyglądać tak:
  252. $acl->addRole(new Zend_Acl_Role('staff'), 'guest');
  253. */
  254. // Grupa editor dziedziczy od grupy staff
  255. $acl->addRole(new Zend_Acl_Role('editor'), 'staff');
  256. // Administrator nie dziedziczy kontroli dostępu
  257. $acl->addRole(new Zend_Acl_Role('administrator'));
  258. ]]>
  259. </programlisting>
  260. </sect2>
  261. <sect2 id="zend.acl.introduction.defining">
  262. <title>Definiowanie kontroli dostępu</title>
  263. <para>
  264. Teraz gdy ACL zawiera stosowne role, możemy ustalić reguły, które
  265. definiują w jaki sposób role mają uzyskiwać dostęp do zasobów.
  266. Mogłeś zauważyć, że nie zdefiniowaliśmy w tym przykładzie żadnych
  267. konkretnych zasobów, co jest uproszczone w celu zilustrowania, że
  268. reguły mają zastosowanie do wszystkich zasobów. Zend_Acl zapewnia
  269. implementację dzięki której reguły mogą być przypisane od ogólnych
  270. do szczegółowych, minimalizując ilość potrzebnych reguł, ponieważ
  271. zasoby oraz role dziedziczą reguły, które są definiowane dla ich
  272. przodków.
  273. </para>
  274. <note>
  275. <para>
  276. W zasadzie Zend_Acl przestrzega danej reguły tylko wtedy, gdy
  277. nie ma zastosowania bardziej szczegółowa reguła.
  278. </para>
  279. </note>
  280. <para>
  281. Możemy więc zdefiniować rozsądny kompleksowy zestaw reguł przy
  282. minimalnej ilości kodu. Aby zastosować podstawowe uprawnienia
  283. zdefiniowane wyżej zrób tak:
  284. </para>
  285. <programlisting role="php"><![CDATA[
  286. $acl = new Zend_Acl();
  287. $roleGuest = new Zend_Acl_Role('guest');
  288. $acl->addRole($roleGuest);
  289. $acl->addRole(new Zend_Acl_Role('staff'), $roleGuest);
  290. $acl->addRole(new Zend_Acl_Role('editor'), 'staff');
  291. $acl->addRole(new Zend_Acl_Role('administrator'));
  292. // Grupa guest może tylko oglądać zawartość
  293. $acl->allow($roleGuest, null, 'view');
  294. /*
  295. alternatywnie, powyższe mogłoby wyglądać tak:
  296. $acl->allow('guest', null, 'view');
  297. */
  298. // Grupa staff dzidziczy uprawnienia view od grupy guest,
  299. // ale także potrzebuje dodatkowych uprawnień
  300. $acl->allow('staff', null, array('edit', 'submit', 'revise'));
  301. // Grupa editor dziedziczy uprawnienia view, edit, submit,
  302. // oraz revise od grupy staff, ale także potrzebuje dodatkowych uprawnień
  303. $acl->allow('editor', null, array('publish', 'archive', 'delete'));
  304. // Administrator nie dziedziczy niczego, ale ma dostęp do wszystkich zasobów
  305. $acl->allow('administrator');
  306. ]]>
  307. </programlisting>
  308. <para>
  309. Wartości <code>null</code> w powyższych wywołaniach metod
  310. <code>allow()</code> oznaczają, że reguły dotyczą wszystkich zasobów.
  311. </para>
  312. </sect2>
  313. <sect2 id="zend.acl.introduction.querying">
  314. <title>Zapytania ACL</title>
  315. <para>
  316. Posiadamy teraz elastyczne ACL, ktore mogą być użyte do określenia,
  317. czy żądająca osoba posiada uprawnienia do przeprowadzenia określonej
  318. akcji w aplikacji web. Przeprowadzenie zapytań jest bardzo proste
  319. poprzez użycie metody <code>isAllowed()</code>:
  320. </para>
  321. <programlisting role="php"><![CDATA[
  322. echo $acl->isAllowed('guest', null, 'view') ?
  323. "allowed" : "denied";
  324. // dozwolone
  325. echo $acl->isAllowed('staff', null, 'publish') ?
  326. "allowed" : "denied";
  327. // zabronione
  328. echo $acl->isAllowed('staff', null, 'revise') ?
  329. "allowed" : "denied";
  330. // dozwolone
  331. echo $acl->isAllowed('editor', null, 'view') ?
  332. "allowed" : "denied";
  333. // dozwolone ponieważ jest dziedziczone od gościa
  334. echo $acl->isAllowed('editor', null, 'update') ?
  335. "allowed" : "denied";
  336. // zabronione ponieważ nie ma reguły dla 'update'
  337. echo $acl->isAllowed('administrator', null, 'view') ?
  338. "allowed" : "denied";
  339. // dozwolone ponieważ administrator ma wszystkie uprawnienia
  340. echo $acl->isAllowed('administrator') ?
  341. "allowed" : "denied";
  342. // dozwolone ponieważ administrator ma wszystkie uprawnienia
  343. echo $acl->isAllowed('administrator', null, 'update') ?
  344. "allowed" : "denied";
  345. // dozwolone ponieważ administrator ma wszystkie uprawnienia]]>
  346. </programlisting>
  347. </sect2>
  348. </sect1>