Wyszukiwarka
Logowanie
Każda aplikacja webowa, tak jak każdy plik na dysku, musi mieć ustawione uprawnienia dla konkretnych użytkowników, lub grup użytkowników. O listach kontroli dostępu ( ang. Access Control List) zapewne słyszał każdy. Jedną z prostszych implementacji takiej listy jest zwykła baza loginów i haseł dostępowych. Co zrobić, gdy jednak potrzebujemy bardziej zaawansowanego systemu kontroli dostępu? Możemy wykorzystać jedną z gotowych bibliotek, np. PHP Generic Access Control List, ale możemy także sami napisać taki system - dobrze jest wtedy wykorzystać częściowo napisane mechanizmy, na przykład pochodzący z Zend Frameworka - Zend_Acl.
Omówmy powyższą tabelę. Zapewne zastanawiacie się, dlaczego "Administrator" nie ma uprawnień prywatnych i dziedziczonych? Z prostego powodu, kontroler dostępu będzie identyfikował rolę. Jeśli rolą będzie "Administrator", to nie sprawdzamy wtedy uprawnień. Jeśli byśmy chcieli utworzyć listę ról korzystając z biblioteki Zend_Acl, powinniśmy napisać takikod:
<?php
$acl = new Zend_Acl();
// Dodajemy rolę - Gość
$acl->addRole(new Zend_Acl_Role("Guest"));
// Dodajemy rolę - Użytkownik - i dziedziczymy z Gościa
$acl->addRole(new Zend_Acl_Role("User"), "Guest");
// Dodajemy rolę - Moderator - i dziedziczymy z Użytkownika
$acl->addRole(new Zend_Acl_Role("Moderator"), "User");
// Dodajemy rolę - Administrator - nie dziedziczymy
$acl->addRole(new Zend_Acl_Role("Administrator"));
?> Bardzo dobrym rozwiązaniem, wykorzystanym w Zend_Acl, jest możliwość ustawienia globalnych uprawnień dla roli. Przykładowo, jeśli chcielibyśmy aby Gość miał globalne uprawnienia na przeglądanie, wystarczy to po prostu ustalić przy tworzeniu uprawnienia. Metoda Zend_Acl::allow() przyjmuje cztery parametry: identyfikator roli, identyfikator zasobu, tablicę z uprawnieniami oraz obiekt typu Zend_Acl_Assert_Interface, czyli obiekt precyzujący dostęp. Dzięki temu, możemy ustalić, że Gość ma prawo do czytania artykułu, chyba, że jego adres IP jest zapisany w tzw. blacklist, czyli liście adresów zablokowanych. Do kwestii precyzowania wrócę w późniejszym etapie. Zajmijmy się teraz utworzeniem zasobu oraz podstawowych uprawnień dostępu do niego.
<?php
// Dodaj zasob - Artykul
$acl->add(new Zend_Acl_Resource("Article"));
// Dodaj uprawnienia Gosciom do przegladania wszystkich zasobow
$acl->allow("Guest", null, "view");
// Dodaj uprawnienia Uzytkownikowi do oceniania artykulu
$acl->allow("User", "Article", "rate");
// Dodaj uprawnienia Moderatorowi do edycji, publikacji i ukrycia artykulu
$acl->allow("Moderator", "Article", array("edit", "public", "hide"));
// Dodaj role Administrator, z maksymalnymi uprawnieniami
$acl->allow("Administrator");
?> Samo sprawdzanie dostępu powinno działać w bardzo prosty sposób. Żądamy informacji na temat tego, czy dana rola ma dostęp do konkretnego uprawnienia zasobu. Wykorzystujemy metodę isAllowed() i mamy wszystko, jak na tacy:
<?php
// Zalozmy, ze uzytkownik ma role Moderator
$userRole = "Moderator";
if ( $acl->isAllowed($userRole, "Article", "edit") ) {
echo "You are allowed to edit this article.";
} else {
echo "You aren’t allowed to edit this article.";
}
?>
Bardzo proste, prawda? Spróbujmy teraz sprecyzować, z jakiego adresu IP musi łączyć się moderator, by miał dostęp do moderacji artykułu. Zatem, utwórzmy obiekt implementujący Zend_Acl_Assert_Interface:
<?php
class AllowedIPAssertion implements Zend_Acl_Assert_Interface {
private $allowedIps;
public function assert(Zend_Acl $acl, Zend_Acl_Role_Interface $role=null, Zend_Acl_Resource_Interface $resource=null, $privilege = null) {
$this->allowedIps = array("127.0.0.1", "192.168.0.1", "83.27.252.11");
return $this->_isIPAllowed($_SERVER["REMOTE_ADDR"]);
}
private function _isIPAllowed($ip_address) {
if ( in_array($ip_address, $this->allowedIps) ) {
return true;
}
return false;
}
}
?>
Wróćmy teraz do tworzenia uprawnień i poprawmy uprawnienia moderatora:
<?php
// Dodaj uprawnienia Moderatorowi do edycji, publikacji i ukrycia artykulu
// ale tylko wtedy, gdy spelnia kryteria AllowedIPAssertion
$acl->allow( "Moderator", "Article", array("edit", "public", "hide"), new AllowedIPAssertion() );
?> Polecam artykuł pana Tomasza Jędrzejewskiego na temat budowy systemu uprawnień http://artykuly.zyxist.com/czytaj.php/system_uprawnien_w_php
Chętnie poczytałbym o propozycjach przechowywania ACL w bazie.
Przedstawiony kod to Role Based Access Control, czyli bazuje na rolach. Uprawnienia przypisuje się roli a nie użytkownikowi.
Acces Control List jest drobnoziarniste, tzn. można przyznać jednemu użytkownikowi prawo do edycji danego obiektu (artykuł, nowość).
Coś to słabo widzę :)
Rola powinna chyba kolekcjonować uprawnienia, a grupa kolekcję użytkowników, w tym przypadku mamy trochę pomieszanie odpowiedzialności, ale jeśli takie były założenia autora to nie a się co czepiać. Implementacji ACL jest tyle, ile implementacji MVC ;)
artykul, slaby. takich powierzchownych opisow acl jest w sieci mnostwo. a co gorsza, wiecej jest w dokumentacji zenda. [jest tez przetlumaczona wersja dokumentacji]
Dobry, bo poruszający konkretny temat z bardziej zaawansowanej dziedziny. Oby takie artykuły też były promowane, nie tylko wyjaśnienia OOP i tym podobne.