是的,我知道有Voter tutorial in cookbook。但我正在寻找一些略有不同的东西。我需要两个不同的黑名单层:
我写了Voter,检查用户的IP是否在数据库中。对于第一个场景,我编写了一个内核侦听器,它检查每个请求并在遇到被禁用户时抛出403:
if (VoterInterface::ACCESS_DENIED === $this->voter->vote($token, $this, array())) {
throw new AccessDeniedHttpException('Blacklisted, punk!');
}
第一个问题在于VoterInterface
本身,这迫使我使用TokenInterface $token
,在这种情况下我并不需要dev
。但我觉得这并不重要。接下来就是我实际上不得不使用AccessDeniedHttpException
因为AccessDeniedException
总是试图将我重定向到登录页面并导致无限重定向循环。我会使用它,因为它在prod
环境中运行得很好,但是当我切换到\Exception
时,我会继续在生成日志中获得503:
[2011-11-21 20:54:04] security.INFO:用一个填充的SecurityContext 匿名令牌[] []
[2011-11-21 20:54:04] request.ERROR: Symfony的\分量\ HttpKernel \异常\ AccessDeniedHttpException: 黑名单,朋克! (未捕获的例外)在xxx第28行[] []
[2011-11-21 20:54:04] request.ERROR:处理时抛出异常 例外 (Symfony的\元器件\ HttpKernel \异常\ AccessDeniedHttpException: 黑名单,朋克!)[] []
从我读过的内容来看,xdebug可能存在问题,但即使我将其关闭也会发生。我也尝试了香草{{1}},它做了同样的事情。任何人都知道为什么会这样?或者对于这种黑名单案例可能有其他一些解决方案。
另外,我不知道如何解决第二种情况,因为我不知道如何在获得令牌之前停止用户。我当前的解决方案是处理InteractiveLoginEvent,检查用户是否被列入黑名单,如果是,则删除他的令牌。它似乎并不安全,我对此并不满意。那么,任何想法如何解决这个问题?我想我只是错过了一些明显的“登录前事件”。
答案 0 :(得分:4)
要拒绝访问整个网站,您可以调整用于保护开发环境的白名单代码。在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.');
}
答案 1 :(得分:4)
对于站点范围的IP限制,最好在apache级别处理它们,因此您的应用程序甚至不会受到请求的影响。如果您试图阻止垃圾邮件发送者,这样您就不会在有时自动化的请求上浪费任何资源。在您的情况下,将拒绝规则写入.htaccess文件是合适的。在较大的设置中,您还可以配置防火墙以阻止特定的IP,以便这些请求甚至根本不会访问您的服务器。
答案 2 :(得分:4)
对于第一个问题 - 有filters in EventDispatcher,因此您可以在Controller启动进程请求之前抛出AccessDeniedHttpException
。
要解决第二个问题 - 如果您使用custom User Provider,则可以在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
}
}
答案 3 :(得分:1)
您也可以在服务器上使用防火墙,例如:http://www.shorewall.net/blacklisting_support.htm 它完全阻止服务器的给定ips。
自动生成这样的黑名单文件,请看下面的例子: http://www.justin.my/2010/08/generate-shorewall-blacklist-from-spamhaus-and-dshield/
答案 4 :(得分:1)
您可以使用我的bundle =>轻松阻止IP和IP范围https://github.com/Spomky-Labs/SpomkyIpFilterBundle
答案 5 :(得分:0)
这不是最佳做法。 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