Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> [Algorytm][Funkcje] do ACL i nawigacji
cve
post
Post #1





Grupa: Zarejestrowani
Postów: 25
Pomógł: 0
Dołączył: 18.09.2009

Ostrzeżenie: (0%)
-----


Witam. Jestem bardzo początkujący w temacie php, ale duużżżooo czytam i zacząłem od jakiegoś czasu rozwijać swój framework i tutaj na forum chciałbym zaprezentować swoje przemyślenia na temat ACL jakie zastosowałem. Otóż w żadnym znanym mi frameworku (Zend, Cake, Symfony, Code Igniter, Kohana) nie umiałem łatwo i szybko zaimplementować takiej jakby automatycznej autoryzacji użytkownika chodziło mi o sprawdzenie praw dostępu do zasobu już na poziomie front-controllera, który zobaczy czy w Liście Kontroli Dostępu znajduje się żądany zasób dla obecnej roli użytkownika i albo 'wpuszcza' go i włącza odpowiednią akcje controllera albo nie 'wpuszcza' i kieruje na wiadomość o braku dostępu. Wydaje mi się to lepszym rozwiązaniem niż pisanie w controllerach instrukcji if i else za każdym razem. Oto jak to jest zaimplementowane:
We folderze config trzymam sobie prosty plik xml, który wgląda następująco:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <acl>
  3. <guest>
  4. <resource name="/" label="Strona główna" />
  5. <resource name="/user/login" label="Zaloguj się" />
  6. <resource name="/user/register" label="Zarejestruj się" />
  7. </guest>
  8.  
  9. <user>
  10. <resource name="/user/logout" label="Wyloguj się" />
  11. <resource name="/user/login" label="" />
  12. <resource name="/user/register" label="" />
  13. </user>
  14.  
  15. <moderator>
  16. </moderator>
  17.  
  18. <admin>
  19. </admin>
  20. </acl>

jak widać chyba nic nie trzeba tutaj tłumaczyć, jedyne co może wzbudzać zainteresowanie to dlaczego w roli user zasoby /user/login i user/register maja pusty label, ale to później wytłumaczę, bo jest jeszcze jedna funkcjonalność tego podejścia, o której za chwile napisze.

A tak wygląda kod:
  1. //najpierw potrzebujemy role, jest ona brana z bazy, a jeśli nie to domyślną jest guest
  2.  
  3. $rola = (isset($_SESSION['user']['rola'])) ? $_SESSION['user']['rola'] : 'guest';
  4.  
  5. //teraz w obiekt acl pobieramy wcześniejszy plik xml
  6.  
  7. $acl = simplexml_load_file('../config/acl.xml');
  8.  
  9. //budujemy tablice dwuwymiarową z rolami i odpowiadającymi im zasobami z pliku xml
  10.  
  11. foreach($acl as $role) {
  12. foreach($role as $res) {
  13. $label = (string)$res['label'];
  14. $ACL[$role->getName()][(string)$res['name']] = ($label == '') ? null : $label;
  15. }
  16. }
  17.  
  18. //teraz czas na funkcje, która tworzy powiązania (dziedziczenie) ról jakie chcemy ze sobą
  19. //oraz tworzy nam na podstawie powiązań nawigacje gotową dla obecnie zalogowanego użytkownika z odpowiednią rolą
  20. //tutaj właśnie są nam potrzebne te puste atrybuty 'label' w zasobach, bo po co mamy wyświetlać zalogowanemu użytkownikowi
  21. //linki do zalogowania albo do zarejestrowania się, skoro on już to zrobił :) Dajemy mu tylko możliwość do wylogowania. :)
  22. //funkcja po prostu wyrzuca sobie takie powtarzające się zasoby z pustymi labelami i daje Nam ładną tablicę z nawigacją.
  23.  
  24. function setInheritAndNav () {
  25.  
  26. $args = func_get_args();
  27.  
  28. foreach($args as $key => $val) {
  29. if($val == null) {
  30. unset($args[$key]);
  31. }
  32.  
  33. }
  34.  
  35. foreach($args as $tab) {
  36. $newArgs[] = $tab;
  37. }
  38.  
  39. $nav = array_reverse($newArgs[0]);
  40.  
  41. foreach($newArgs as $tab) {
  42. if($tab != null) {
  43.  
  44. $nav += array_reverse($tab);
  45. }
  46. }
  47.  
  48. foreach($nav as $key => $val) {
  49. if($val == null) {
  50. unset($nav[$key]);
  51. }
  52. }
  53.  
  54. $nav = array_reverse($nav);
  55.  
  56. return $nav;
  57.  
  58. }
  59.  
  60. //tutaj w prosty sposób definiujemy sobie jakie role jak mają zostać dziedziczone
  61. //korzystając z wyżej wymienionej funkcji, dziedziczenie działa od lewej strony, czyli
  62. //tak jak np. dla admina: admin -> moderator -> user -> guest ('->' oznacza 'dziedziczy po'),
  63. //a nawet mozemy zrobic tak guest -> user -> moderator -> admin :) wtedy guest dziedziczy po naszych wszystkich rolach :)
  64.  
  65. $guest = setInheritAndNav($ACL['guest']);
  66. $user = setInheritAndNav($ACL['user'], $ACL['guest']);
  67. $admin = setInheritAndNav($ACL['admin'], $ACL['moderator'], $ACL['user'], $ACL['guest']);
  68.  
  69. //tworzymy sobie dwuwymiarową tablicę z nawigacjami dla ról
  70.  
  71. $NAV = array('guest' => $guest, 'user' => $user, 'admin' => $admin);
  72.  
  73. //żeby w prosty sposób sprawdzić sobie właśnie czy żądany zasób znajduje się ACL:
  74.  
  75. $resources = array_keys($NAV[$rola]);
  76.  
  77. //i działanie prostego front-controllera:
  78. //w adresie trzymam zmienną url, która przechowuje mi kombinację czystych urli np. '/index/index/' lub '/user/login' albo nic czyli '/' itp.
  79.  
  80. $_url = strip_tags($_GET['url']);
  81.  
  82. $urlArray = array();
  83. $urlArray = explode('/', $_url);
  84.  
  85. $_controller = $urlArray[0] ? $urlArray[0] : 'index';
  86. $_action = $urlArray[1] ? $urlArray[1] : 'index';
  87. $_parameter = $urlArray[2] ? $urlArray[2] : '1';
  88.  
  89. if(in_array('/'.$_controller.'/'.$_action, $resources) || in_array('/', $resources)) {
  90.  
  91. $controllerName = ucfirst($_controller).'Controller';
  92.  
  93. $run = new $controllerName($_controller, $_action, $NAV[$rola]);
  94.  
  95. $run->$_action($_parameter);
  96.  
  97. }
  98. else
  99. {
  100. URL::_redirect();
  101. }


prawie wszystko dzieje się metodą strukturalną, bo po co obciążać cały system obiektówką, tam gdzie nie jest ona potrzebna (IMG:style_emoticons/default/smile.gif) .

Chciałbym usłyszeć jakieś opinie lub uwagi co można jeszcze poprawić, usprawnić lub zmienić.
Go to the top of the page
+Quote Post

Posty w temacie


Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 22.08.2025 - 16:00