yaotzin
11.01.2011, 22:36:06
Witam
Tak mnie zastanawia w jaki sposób w symfony można chronić dane przed nieautoryzowanym usunięciem. Nie chodzi mi oto, że można powtórzyć żądanie logowania czy też pozwolić użytkownikom o określonych prawach pozwalać na usuwanie danych - te rzeczy są oczywiste. Bardziej mnie interesuje w jaki sposób maskuje się URL itp. Wiem, że może pytanie brzmi lamersko, ale zaczęło mnie to dzisiaj zastanawiać, gdy tak przyjrzałem się różnym projektom w symfony, gdzie usuwanie jest realizowane na zasadzie adresu URL jak example.com/my_module/delete/id/1. Jak widać usuwanie odbywa się po id - które zapewne może być kluczem głównym. Jak widać taki klucz łatwo zgadnąć. Co ciekawe klucze składające się z trzech części również nie są bezpieczne. Więc co, generowanie ich ze znaków losowych. Czy może symfony oferuje jakieś własne mechanizmy zabezpieczeń. Np. trzyma informacje o modelu gdzieś w pamięci itp. ? To są pierwsze dni z symfony - więc stąd moje pytania.
Pozdrawiam
Crozin
11.01.2011, 23:45:25
Po pierwsze, rzeczy typu "dodaj", "usuń", "edytuj" itd. powinny opierać się na żądaniach POST, nie GET. Chodzi o przesyłanie parametrów w "ciele" żądania, nie w URLu. Mimo iż i to ostatnie może być z powodzeniem stosowane do takich rzeczy, POST jest po prostu wygodniejsze i prostsze w obsłudze.
Co do tego, że można sobie ręcznie podmienić parametr żądania... no cóż... można i tyle. Sprawdź po prostu czy dany użytkownik ma prawo taką operację wykonać i jeżeli ma to ją wykonaj. Nie jesteś w stanie rozróżnić tego czy ktoś kliknął w przycisk "Usuń" czy sam sobie ustawił odpowiednie parametry ręcznie.
W jednym z prostszych projektów sprawdzam takie rzeczy bezpośrednio na początku akcji. W uproszczeniu:
public function executeDelete(sfWebRequest $request)
{
$object = $this->getRoute()->getObject();
$this->forward404Unless(
$object ->isOwnedBy($this->getUser()->getGuardUser()) || $this->getUser()->isSuperAdmin() // możesz tutaj jakieś bardziej skomplikowane warunki wrzucić
);
$object ->delete();
$this->redirect('@object');
}
yaotzin
12.01.2011, 08:24:42
Obaj macie jak najbardziej rację. Co do Crozin'a POST do delete i edytuj, czyli co JavaScript? No chyba, że wszystko zamykasz w form, nawet tabele (tak jak to jest popularne w JAVA).
Crozin
12.01.2011, 09:14:50
Po prostu wszystko obejmujesz formularzami.
thek
12.01.2011, 09:44:37
To czy użyjesz get czy post jest sprawą drugorzędną. Obie formy i tak można łatwo spreparować. Z tym, że get łatwiej z racji większej widoczności parametrów. To co najistotniejsze to sprawdzanie uprawnień po nadejściu żądania. Nie może być tak, że user modyfikuje nie swoje dane. Co z tego że ma prawa do edycji, usuwania czy tworzenia, skoro próbuje je wykorzystać dla nie swoich zasobów? Jest to z reguły prosto rozwiązywane, ponieważ jakoś łączysz zazwyczaj dane usera z nim poprzez id lub w inny sposób jednoznacznie go identyfikujący. Sprawdzasz więc choćby id usera w sesji i id właściciela zasobu (no chyba, że masz jeszcze grupowe prawa dostępu). To z reguły wystarcza by wykluczyć lub potwierdzić prawa do zasobu. Tylko uważaj na grupy uprzywilejowane. Mi się kilka razy zdarzyło o tym zapomnieć i odciąłem w ten sposób admina, który był rozpoznawany jako user bez praw do modyfikacji zasobów innych osób
yaotzin
12.01.2011, 11:08:38
Cytat(Crozin @ 12.01.2011, 09:14:50 )

Po prostu wszystko obejmujesz formularzami.
A co z WC3?
Cytat(thek)
Sprawdzasz więc choćby id usera w sesji i id właściciela zasobu (no chyba, że masz jeszcze grupowe prawa dostępu). To z reguły wystarcza by wykluczyć lub potwierdzić prawa do zasobu. Tylko uważaj na grupy uprzywilejowane. Mi się kilka razy zdarzyło o tym zapomnieć i odciąłem w ten sposób admina, który był rozpoznawany jako user bez praw do modyfikacji
No na chwilę obecną dokładnie tak robię.
Crozin
12.01.2011, 12:44:27
Cytat
A co z WC3?
A co ma być? Formularz może być wepchany w niemal wszystko jak i niemal wszystko może być wepchane w formularz. A sam standard nie określa jakie dane powinny być przesyłane - nie ma żadnego problemu jeżeli cały formularz składa się wyłącznie z przycisku "wyślij".
Cytat
To czy użyjesz get czy post jest sprawą drugorzędną.
Chodziło mi tutaj o CSRF. Oczywiście obie metody wymagają zabezpieczenia w postaci chociażby jednorazowego tokenu.
bikerszymek
12.01.2011, 15:13:04
Nie każdy to wie ale symfony obsługuje coś takiego jak żądania DELETE, sam generuje sobie token CSRF.
w szablonie:
<?php echo link_to
('usuń', 'delete_object', array('id' => $Object->getId()), array('method' => 'delete', 'confirm' => 'Na pewno usunąć?')) ?>
w akcji:
$this->forward404Unless($request->isMethod(sfRequest::DELETE));
Crozin
12.01.2011, 15:17:59
@bikerszymek: To nadal jest żądanie POST, tylko z dodatkowym parametrem na podstawie którego Sf potrafi rozpoznać, że jest to emulacja metody DELETE czy PUT. Na dobrą sprawę jest to w tym wątku kompletnie bez znaczenia.
bikerszymek
12.01.2011, 15:28:33
Cytat(Crozin @ 12.01.2011, 15:17:59 )

@bikerszymek: To nadal jest żądanie POST, tylko z dodatkowym parametrem na podstawie którego Sf potrafi rozpoznać, że jest to emulacja metody DELETE czy PUT. Na dobrą sprawę jest to w tym wątku kompletnie bez znaczenia.
To że jest to POST nie musisz mnie uświadamiać. Nie rozumiem Twojej wątpliwości co do samej emulacji DELETE, sam zaproponowałeś podobne rozwiązanie - a po co pisać coś co jest już w core frameworka. Autor wątku chciał rozwiązanie dotyczące symfony to mu je podałem, w połączeniu z tym co napisał @LBO będzie to ono optymalne.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę
kliknij tutaj.