[英]How to create IP blacklist in Symfony2?
是的,我知道食譜中有選民教程 。 但我正在尋找一些略有不同的東西。 我需要兩個不同的黑名單層:
我寫了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.