簡體   English   中英

如何在Symfony2中創建IP黑名單?

[英]How to create IP blacklist in Symfony2?

是的,我知道食譜中選民教程 但我正在尋找一些略有不同的東西。 我需要兩個不同的黑名單層:

  1. 拒絕某些IP訪問整個站點
  2. 拒絕某些IP登錄

我寫了Voter來檢查用戶的IP是否在數據庫中。 對於第一個場景,我編寫了一個內核偵聽器,它檢查每個請求並在遇到被禁用戶時拋出403:

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

第一個問題在於VoterInterface本身,這迫使我使用TokenInterface $token ,在這種情況下我並不需要它。 但我覺得這並不重要。 接下來的事情是我實際上不得不使用AccessDeniedHttpException因為AccessDeniedException總是嘗試將我重定向到登錄頁面,並在這種情況下導致無限的重定向循環。 我和它一起生活,因為它在dev環境中運行得很好,但是當我切換到prod我繼續在prod日志中獲得503:

[2011-11-21 20:54:04] security.INFO:用匿名令牌填充SecurityContext [] []

[2011-11-21 20:54:04] request.ERROR:Symfony \\ Component \\ HttpKernel \\ Exception \\ AccessDeniedHttpException:黑名單,朋克! (未捕獲的例外)在xxx第28行[] []

[2011-11-21 20:54:04] request.ERROR:處理異常時拋出異常(Symfony \\ Component \\ HttpKernel \\ Exception \\ AccessDeniedHttpException:Blacklisted,punk!)[] []

從我所看到的,它可能是xdebug的問題,但即使我關閉它也會發生。 我也嘗試了vanilla \\Exception ,它做了同樣的事情。 任何人都知道為什么會這樣? 或者可能是針對這種黑名單案例的其他解決方案。

另外,我不知道如何解決第二種情況,因為我不知道在獲得令牌之前如何停止用戶。 我目前的解決方案是處理InteractiveLoginEvent ,檢查用戶是否被列入黑名單,如果是,則刪除他的令牌。 它似乎並不安全,我對此並不滿意。 那么,任何想法如何解決這個問題? 我想我只是錯過了一些明顯的“登錄前事件”。

對於第一個問題 - EventDispatcher中過濾器 ,因此您可以在Controller啟動進程請求之前拋出AccessDeniedHttpException

對於第二個問題 - 如果您使用自定義用戶提供程序,您可以檢查UserRepository禁止IP地址。

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
    }

}

要拒絕訪問整個網站,您可以調整用於保護開發環境的白名單代碼。 在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.');
}

對於站點范圍的IP限制,最好在apache級別處理它們,因此您的應用程序甚至不會受到請求的影響。 如果您試圖阻止垃圾郵件發送者,這樣您就不會在有時自動化的請求上浪費任何資源。 在您的情況下,將拒絕規則寫入.htaccess文件是合適的。 在較大的設置中,您還可以配置防火牆以阻止特定IP,以便這些請求甚至根本不會訪問您的服務器。

您可以使用我的捆綁包輕松阻止IP和IP范圍=> https://github.com/Spomky-Labs/SpomkyIpFilterBundle

您也可以在服務器上使用防火牆,例如: http//www.shorewall.net/blacklisting_support.htm ,它可以完全阻止服務器的給定ips。

要自動生成這樣的黑名單文件,請查看以下示例: http//www.justin.my/2010/08/generate-shorewall-blacklist-from-spamhaus-and-dshield/

這不是最佳做法。 Insight(由Sensio分析)返回:“不鼓勵使用PHP響應函數(如此處的header()),因為它繞過了Symfony事件系統。請改用HttpFoundationResponse類。” 並且“不應該使用$ _SERVER超級全局”。

<?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);

SensioInsight沒問題

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM