Autor wpisu: sokzzuka, dodany: 03.10.2010 23:59, tagi: php
Zyx ma ciekawe przemyślenia, ja również je mam (tak mi się zdaje) więc tym razem moje RE, będzie dotyczyć jego artykułu pt. poeksperymentujmy z kontrolą uprawnień.
Przedstawił on w swoim artykule sposób na weryfikacje czy dany kod ma dostęp do innego kodu na podstawie domen. Domena była obszarem gdzie obowiązywała dana polityka bezpieczeństwa, jeżeli zewnętrzny kod chciał na niej wykonać jakąś operacje, musiał wywołać metodę safeOperation
z argumentami charakterystycznymi dla danej operacji i podać domenę z której pochodzi. Metoda safeOperation
weryfikowała za pomocą policyManagera
czy kod z innej domeny ma prawo wywołać daną operację i jeżeli ich nie posiadał to wyrzucany był wyjątek.
Rozwiązanie, które tu przedstawię jest w pewnym sensie generalizacją koncepcji Zyx-a. Na czym ono polega ?
Pierwsze założenie jest takie, że wszystkimi obiektami (a przynajmniej tymi które chcemy zabezpieczyć) zarządzą kontener IoC (inversion of control). Jest to maszynka, która tworzy nam i konfiguruje obiekty. Mój kontener IoC ma tą ciekawą właściwość, że pozwala zwracać zamiast żądanego obiektu jego proxy. Proxy jest obiektem przez którego przelatują wszystkie żądania do docelowego obiektu i posłuży on do kontroli uprawnień.
Cała idea leży w tym, że proxy przy próbie wywołania metody na obiekcie docelowym, sprawdzi w Acl, czy aktualny użytkownik (może być cokolwiek innego np wywołujący obiekt) ma uprawnienia do wywołania owej metody i jeżeli nie to rzuci wyjątkiem.
Żeby nie być gołosłownym, przedstawię fragmenty kodu jak to działa, na końcu artykułu będzie też link do kompletnego przykładu razem z moim kontenerem IoC.
Po pierwsze konfiguracja IoC (pełną informacje o konfiguracji znajdziesz w artykule o kontenerze IoC):
<object-config> <application> <!-- For now empty, objects declared here will be cached by APC or something similiar --> </application> <session> </session> <request> <object class="Foo1"> <property name="param2">other_baz</property> <property name="param1">baz</property> <proxy class="AccessProxy" /> </object> <object class="AccessProxy"> <property name="acl" type="class">Acl</property> </object> <object class="Acl"> <property name="user" type="class">User</property> </object> </request> </object-config>
I klasy biorące udział w eksperymencie: klasa docelowa:
class Foo1 { private $param1; private $param2; function __construct($param1, $param2){ $this->param1 = $param1; $this->param2 = $param2; } function doHello(){ echo 'hello <br/>'; } function doFoo(){ echo 'foo <br/>'; } }
Klasa Acl:
class Acl { protected $_user; public function __construct(User $user){ $this->_user = $user; } public function isCallable($class, $method){ if($this->_user->id == 10 and $method == 'doHello'){ return true; } if($this->_user->id == 15 and $method == 'doFoo'){ return true; } return false; } }
Minimalistyczna klasa użytkownika
class User { public $id = 10; }
oraz najważniejsze – klasa proxy: