2011-11-21 12 views
9

Tak, wiem, że jest Voter tutorial in cookbook. Ale szukam czegoś nieco innego. Potrzebuję dwóch różnych warstw czarnych list:Jak utworzyć czarną listę IP w Symfony2?

  1. zaprzeczyć pewien IP, aby uzyskać dostęp Cała strona
  2. zaprzeczyć pewien IP do logowania

pisałem wyborca, który sprawdza, czy IP autora znajduje się w bazie danych. Na pierwszym scenariuszu napisałem słuchacza jądra, który sprawdza każdy wniosek i rzuca 403 w przypadku napotkania zakazane użytkownik:

if (VoterInterface::ACCESS_DENIED === $this->voter->vote($token, $this, array())) { 
    throw new AccessDeniedHttpException('Blacklisted, punk!'); 
} 

Pierwszy problem polega na VoterInterface się, co mnie zmusza do korzystania TokenInterface $token, który tak naprawdę nie potrzeba w tym przypadku. Ale to nie ma znaczenia, jak sądzę. Następnie musiałem użyć AccessDeniedHttpException jako AccessDeniedException zawsze próbuje przekierować mnie do strony logowania i powoduje nieskończoną pętlę przekierowań w tym przypadku. Chciałbym z nią żyć, jak to działa dobrze w środowisku dev, ale kiedy przełączyć się prod Wciąż dostaję 503 z następujących w dzienniku Prod:

[2011-11-21 20:54:04] security.INFO: Populated SecurityContext with an anonymous Token [] []

[2011-11-21 20:54:04] request.ERROR: Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException: Blacklisted, punk! (uncaught exception) at xxx line 28 [] []

[2011-11-21 20:54:04] request.ERROR: Exception thrown when handling an exception (Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException: Blacklisted, punk!) [] []

Z tego co czytałem, to może być problem z xdebug, ale dzieje się tak nawet wtedy, gdy go wyłączam. Próbowałem też wanilii \Exception i robi to samo. Ktoś ma pojęcie, dlaczego tak się dzieje? A może jakieś inne rozwiązanie takiej sprawy na czarnej liście.

Ponadto, nie mam pojęcia, jak rozwiązać drugi przypadek, ponieważ nie wiem, jak zatrzymać użytkownika, zanim zostanie mu przydzielony token. Moje obecne rozwiązanie polega na sprawdzaniu, czy użytkownik jest na czarnej liście, a jeśli tak, usunięcie jego tokena. To nie wydaje się być bezpieczne i nie czuję się z tym dobrze. Więc, jakikolwiek pomysł, jak rozwiązać ten problem? Chyba brakuje mi oczywistego "zdarzenia poprzedzającego logowanie".

+0

w komunikacie o błędzie, myślisz, że wyjątek w nawiasach jest wyjątek, który jest obsługiwany lub wyjątek, który jest generowany? – greg0ire

+0

Powiedziałabym, że to ten, który jest obsługiwany, ale myślał też, jeśli coś takiego się nie dzieje. –

+0

Wyszukaj w kodzie "Wyjątek zgłoszony podczas obsługi", zobaczysz, że jest to druga opcja => jest pętla – greg0ire

Odpowiedz

4

Aby odmówić dostępu do całej witryny, można dostosować kod białej listy używany do zabezpieczenia środowiska programisty. Trzymać coś takiego w app.php:

if (in_array(@$_SERVER['REMOTE_ADDR'], array('127.0.0.1', '1.2.3.4',))) { 
    header('HTTP/1.0 403 Forbidden'); 
    exit('You are not allowed to access this site.'); 
} 
+0

To nie jest najlepsza praktyka. Insight (analiza przez Sensio) zwraca: "Korzystanie z funkcji odpowiedzi PHP (takich jak header() tutaj) jest odradzane, ponieważ omija system zdarzeń Symfony. Zamiast tego użyj klasy HttpFoundationResponse." i "$ _SERVER super globalny nie powinien być używany." Zobacz moją odpowiedź http://stackoverflow.com/a/34897282/3066708 – johnnyevolunium

+0

@johnnyevolunium To dziwne, to, czego używają dla środowiska dev. Na przykład, zobacz dystrybucję CMF https://github.com/symfony-cmf/symfony-cmf-standard/blob/master/web/app_dev.php#L16 (zmieniła się nieco w ciągu ostatnich 5 lat, ale wciąż ma problem, o którym wspomniałeś) – MrGlass

+0

Symfony-Cmf jest wciąż aktualne? Wciąż Symfony 2.3, nie było jeszcze Insight. – johnnyevolunium

4

Dla ograniczenia IP Site szerokości najlepiej obsługiwać je na poziomie apache, więc aplikacja nawet nie oberwać wniosku. W przypadku, gdy próbujesz powstrzymać spamera, w ten sposób nie tracisz żadnych zasobów na swoich czasami automatycznych żądaniach. W twoim przypadku odpowiednie byłoby zapisanie reguł odmowy do pliku .htaccess. W większych konfiguracjach można również skonfigurować zaporę sieciową, aby blokować określone adresy IP, aby te żądania w ogóle nie trafiały na serwer.

+0

Jedynym problemem w tym przypadku jest ładowanie adresów IP z bazy danych. Czy to w ogóle jest możliwe? –

+0

jako komentarz do listy dyskusyjnej symfony2, pozwól aplikacji napisać do pliku htaccess. Osobiście podoba mi się rozwiązanie z mrglass. – c33s

4

Do pierwszego problemu - istnieją filters in EventDispatcher, więc można rzucić AccessDeniedHttpException przed żądanie procesu uruchamiania kontrolera.

Do drugiego problemu - jeśli używasz custom User Provider, możesz sprawdzić zablokowane adresy IP w UserRepository.

namespace Acme\SecurityBundle\Entity; 
//… some namespaces 
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; 

/** 
* UserRepository 
*/ 
class UserRepository extends … implements … 
{ 

    public function loadUserByUsername($username) 
    { 
     if ($this->isBanned()) { 
      throw new AccessDeniedHttpException("You're banned!"); 
     } 
     //… load user from DB 
    } 

    //… some other methods 

    private function isBanned() 
    { 
     $q = $this->getEntityManager()->createQuery('SELECT b FROM AcmeSecurityBundle:BlackList b WHERE b.ip = :ip') 
      ->setParameter('ip', @$_SERVER['REMOTE_ADDR']) 
      ->setMaxResults(1) 
     ; 
     $blackList = $q->getOneOrNullResult(); 

     //… check if is banned 
    } 

} 
0

To nie jest najlepszym rozwiązaniem. Insight (analiza przez Sensio) zwraca: "Korzystanie z funkcji odpowiedzi PHP (takich jak header() tutaj) jest odradzane, ponieważ omija system zdarzeń Symfony. Zamiast tego użyj klasy HttpFoundationResponse." i "$ _SERVER super globalny nie powinien być używany."

<?php 

use Symfony\Component\HttpFoundation\Request; 
use Symfony\Component\HttpFoundation\Response; 

$loader = require_once __DIR__.'/../app/bootstrap.php.cache'; 

require_once __DIR__.'/../app/AppKernel.php'; 


$request = Request::createFromGlobals(); 

$client_ip = $request->getClientIp(); 
$authorized_hosts = ['127.0.0.1', 'fe80::1', '::1', 'localhost', 'yourIpAddress']; 

// Securisation 
if (!in_array($client_ip, $authorized_hosts)) { 
    $response = new Response(
     "Forbidden", 
     Response::HTTP_FORBIDDEN, 
     array('content-type' => 'text/html') 
    ); 
    $response->send(); 
    exit(); 
} 

$kernel = new AppKernel('prod', false); 
$kernel->loadClassCache(); 
$response = $kernel->handle($request); 
$response->send(); 
$kernel->terminate($request, $response); 

To ok SensioInsight

Powiązane problemy