如何在Symfony2中的请求订阅者/侦听者中检查用户的IP?

时间:2015-11-20 09:38:27

标签: symfony fosuserbundle

我的应用程序的某些用户将附加allowedIPs数组。验证Voterguide用于将IP列入黑名单,我可以根据谁进行身份验证来修改用户IP的白名单。

我在这里看到的问题是用户在一个允许的网络中进行身份验证的情况,然后切换到另一个不允许用户连接的网络。

我认为解决方案是拥有kernel.request事件的订阅者,如果不允许IP,我将取消对用户的授权。

这种IP检查对每个请求都是一种愚蠢的方法吗?如果不是,我如何在事件订阅者中获得经过身份验证的用户? GetResponseEventapi docs)似乎没有提供任何方法来获取经过身份验证的用户(如果存在)。

编辑:正如Cerad建议的那样,我选了一个选民。

选民班级

<?php

namespace My\UserBundle\Security;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
use Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Psr\Log\LoggerInterface;
use My\UserBundle\Entity\User;

class ValidClientIpVoter extends AuthenticatedVoter
{
    private $container;
    private $logger;

    public function __construct(ContainerInterface $container, LoggerInterface $logger)
    {
        $this->container = $container;
        $this->logger = $logger;
    }

    public function vote(TokenInterface $token, $object, array $attributes)
    {
        $request = $this->container->get('request');
        $user = $token->getUser();

        // vote on instances of our User class
        if($user instanceof User) {
            $allowed_ips = $user->getAllowedIps();

            // only vote if there actually are limitations
            if(is_array($allowed_ips) && count($allowed_ips)) {
                $this->logger->debug(sprintf('ValidClientIpVoter: Validating allowed IPs for user #%d', $user->getId()));

                // deny access if current request's IP is not allowed for the user
                if(!in_array($request->getClientIp(), $allowed_ips)) {
                    $this->logger->notice(sprintf('ValidClientIpVoter: Invalid client IP for user #%d', $user->getId()));

                    return VoterInterface::ACCESS_DENIED;
                }
            }
        }

        return VoterInterface::ACCESS_ABSTAIN;
    }

}

更改为security.yml以使投票一致

security:
    access_decision_manager: 
        strategy: unanimous

最后是服务定义

services:
   valid_client_ip_voter:
        class:      My\UserBundle\Security\ValidClientIpVoter
        arguments:  [@service_container, @monolog.logger]
        public:     false
        tags:
            -       { name: security.voter }

1 个答案:

答案 0 :(得分:0)

要获取当前用户,请将security.token_storage服务注入您的侦听器:http://symfony.com/doc/current/book/security.html#retrieving-the-user-object

我实际上会听kernel.controller只是为了确保用户可用。

另一方面,选民在每次访问资源时都会被调用,所以我不清楚为什么即使ip发生变化,你现有的方法也不会起作用。