2011-10-13 15 views
6

Mam sytuacji gdzie potrzebne do uruchomienia kodu, jeśli użytkownik próbuje dostępu zabezpieczonego URL i jest nie uwierzytelnione/autoryzowane.Czy można sprawdzić programowo, czy adres URL/ścieżka jest chroniona za zaporą sieciową?

Domyślnie Symfony obsługuje nieuwierzytelnionych użytkowników poprzez przekierowanie lub przekierowanie użytkownika do formularza logowania. Chciałbym temu zapobiec, jeśli metodą żądania jest POST, a zamiast tego echo obiektu JSON.

Najlepszym sposobem mogę myśleć, aby obsłużyć tego celu jest stworzenie własnego słuchacza, który nasłuchuje na razie kernel.request i sprawdza dwie rzeczy:

  • sprawdza, czy metoda żądania jest POST
  • sprawdza czy użytkownik jest w pełni uwierzytelniony

Jeśli jest to żądanie POST, a użytkownik nie jest w pełni uwierzytelniony, wywołuję echo obiektu JSON.

Ale mój słuchacz (expectedly) wypalania dla wszystkich żądań - Chciałbym ograniczyć go tylko sprawdzić, czy żądanie dotyczy zawartości chronionej przez firewall. Czy można to sprawdzić programowo?

Mam też dokuczliwy podejrzenie istnieje prostszy sposób, aby przejść na ten temat, ale nie mogę tego rozgryźć, więc jeśli ktoś ma jakieś wskazówki, chciałbym je :)

Edycja usłyszeć
@Problematic - powodem, dla sprawdzenia tylko zaporę żądań jest, bo mam pewne wnioski, które nie są zaporę, a jeśli mój kod jest zwolniony, będę otrzymywać ww obiekt JSON zamiast realnej odpowiedzi na wniosek.

W tej chwili, jeśli nie jestem zalogowany i wysyłam żądanie POST do api/get/something (które znajduje się za firewallem), Symfony zwraca kod HTML opisujący stronę logowania. Zamiast tego chcę po prostu powtórzyć coś takiego, jak {error: 'User is not authorized'}. Ale chcę, żeby tak było tylko w przypadku żądań POST.

+0

Jaki jest powód sprawdzania tylko zapór ogniowych? – Problematic

+0

@Problematic, zobacz moją edycję –

Odpowiedz

3

myślę, że szło o to w niewłaściwy sposób. Chciałem wiedzieć, czy adres URL znajduje się za zaporą, ale sądzę, że powinienem był spróbować dowiedzieć się, czy bieżący użytkownik był autoryzowany do tego żądania. W esense, wiedząc, że użytkownik nie ma dostępu do adresu URL, oznacza to, że adres URL musi znajdować się za zaporą ogniową, w przeciwnym razie dostęp nie mógłby zostać odrzucony.

Mając to na uwadze, udało mi się uzyskać pożądany efekt końcowy. Jest to dość proste, gdy zdajesz sobie sprawę, jak działa mechanizm bezpieczeństwa ...

  • Symfony\Component\Security\Http\Firewall nasłuchuje zdarzenia kernel.request
  • następnie Zapora wywołuje szereg detektorów zdarzeń, które są zarejestrowane w security.yml
  • Jeżeli każde naruszenie bezpieczeństwa (tzn. użytkownik próbujący uzyskać dostęp do czegoś bez zalogowania się) zostanie wykryty, zostanie zgłoszony kod AccessDeniedException i zostanie wywołane zdarzenie kernel.exception.
  • Symfony/Component/Security/Http/Firewall/ExceptionListener nasłuchuje zdarzenia i wystrzeliwuje swoje onKernelException metodę, która decyduje, co jest kolejnym krokiem jest.W moim przypadku, to rozpocząć proces uwierzytelniania

Od rozpoczęcia procesu uwierzytelniania jest to, co chciałem uniknąć, napisałem mój własny detektor zdarzeń, który przechwytuje kernel.exception przed Symfony na ExceptionListener robi. Dałem detektor zdarzeń priorytetem 1.

Jest to metoda pisałem:

public function handleException(GetResponseForExceptionEvent $event) { 
     $exception = $event->getException(); 
     $request = $event->getRequest(); 
     if ($request->getMethod() == 'POST') { 
      if ($exception instanceof AccessDeniedException) { 
       $response = new Response({err: 'not logged in'}); 
       $event->setResponse($response); 
      } 
     } 
    } 

Dopóki użytkownik nie jest uprawniony, a metoda jest żądanie POST, obiekt JSON jest zwracane (co również zatrzymuje propagację zdarzenia) zamiast kodu HTML strony logowania. W przeciwnym razie zareagują inni słuchacze kernel.exception, a Symfony zajmie się swoimi sprawami.

Pierwotne pytanie pozostaje bez odpowiedzi, ale myślę, że można to osiągnąć, sprawdzając, czy użytkownik ma dostęp do akcji. Symfony\Component\Security\Core\Authorization\AccessDecisionManager wygląda na to, że byłoby to pomocne.

Edit
Nie wiem, czy ta metoda tylko obsługuje użytkowników, że nie jest zalogowany. Nie testowałem go jeszcze, ale myślę, że będzie to również ogień, jeśli (zalogowany) użytkownik próbuje uzyskać dostęp do działania, które wymaga roli, której nie przyznano. Jeśli spowoduje to problem, spróbuję zmodyfikować go, aby używał metody 'isFullFledged($token), aby dbać tylko o użytkowników, którzy nie są zalogowani.

+0

Jeśli wysyłasz odpowiedź json, powinieneś dodać czek, aby sprawdzić, czy jest to żądanie ajaxowe, używając: $ request-> isXmlHttpRequest(). Właśnie to zamieniłem domyślną metodę uwierzytelniania na metodę ajaxową. – HappyDeveloper

+0

@HappyDeveloper dzięki za napiwek, ale nadal używam zwykłego formularza logowania. Po prostu musiałem zareagować inaczej, jeśli do działań chronionych wprowadzono żądanie POST, a użytkownik nie był zalogowany. –

Powiązane problemy