如何在Sym2中访问请求对象FOSUserBundle自定义UserChecker

时间:2015-09-08 11:53:53

标签: php symfony login fosuserbundle

我正在使用带有FOSUserBundle的Synfony2,我有一个自定义userChecker,我想验证用户的主机(我们有几个主机指向同一个IP)。我的问题是在我的自定义userChecker中我无法访问REQUEST,因此不是请求的主机。

这是我的用户检查程序代码

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

//Override by Mattias

namespace BizTV\UserBundle\Controller;
//namespace Symfony\Component\Security\Core\User;

use Symfony\Component\Security\Core\Exception\CredentialsExpiredException;
use Symfony\Component\Security\Core\Exception\LockedException;
use Symfony\Component\Security\Core\Exception\DisabledException;
use Symfony\Component\Security\Core\Exception\AccountExpiredException;

use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserChecker as OriginalUserChecker;

use Symfony\Component\HttpFoundation\Request as Request; //ADDED BY MW

/**
 * UserChecker checks the user account flags.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class UserCheckerNew extends OriginalUserChecker
{
    /**
     * {@inheritdoc}
     */
    public function checkPreAuth(UserInterface $user)
    {
/*
        //Test for companylock...
        if ( !$user->getCompany()->getActive() ) {
            throw new LockedException('The company of this user is locked.', $user);
        }

        if ( $user->getLocked() ) {
            throw new LockedException('The admin of this company has locked this user.', $user);
        }
*/

        if (!$user instanceof AdvancedUserInterface) {
            return;
        }

        if (!$user->isCredentialsNonExpired()) {
            throw new CredentialsExpiredException('User credentials have expired.', $user);
        }



    }

    /**
     * {@inheritdoc}
     */
    public function checkPostAuth(UserInterface $user)
    {

        //Test for companylock...
        if ( !$user->getCompany()->getActive() ) {
            throw new LockedException('The company of this user is locked.');
        }    

        if ( $user->getLocked() ) {
            throw new LockedException('The admin of this company has locked this user.');
        }

/*
Validate HOST here
*/

        if (!$user instanceof AdvancedUserInterface) {
            return;
        }

        if (!$user->isAccountNonLocked()) {
            throw new LockedException('User account is locked.', $user);
        }

        if (!$user->isEnabled()) {
            throw new DisabledException('User account is disabled.', $user);
        }

        if (!$user->isAccountNonExpired()) {
            throw new AccountExpiredException('User account has expired.', $user);
        }
    }
}

在checkPostAuth函数中,我尝试了不同的方法,例如传递请求

public function checkPostAuth(UserInterface $user, Request $request)

错误说我的覆盖必须符合原始/接口。

尝试在控制器中获取请求

$this->container->get('request_stack')->getCurrentRequest();

或者像这样

$currentHost = $request->getHost();

或者像这样

$cont = $this->getContainer();

或者像这样

$request = $this->getRequest();

或者像这样

$request = $container->get('request');

然而没有运气=)我不是Symfony2大师,你可以说,我在这里从臀部射击=)

根据gp-sflover的回答为config.yml添加了参数,我的config.yml现在看起来像这样:

services:
    security.user_checker:
        class: BizTV\UserBundle\Controller\UserCheckerNew
        arguments: [ "@request" ]
        scope: request
        public: true

在范围之前传递的错误:请求已添加到配置中:

Scope Widening Injection detected: The definition "security.user_checker" references the service "request" which belongs to a narrower scope. Generally, it is safer to either move "security.user_checker" to scope "request" or alternatively rely on the provider pattern by injecting the container itself, and requesting the service "request" each time it is needed. In rare, special cases however that might not be necessary, then you can set the reference to strict=false to get rid of this error.'

添加范围时:请求返回非常类似的错误

Scope Widening Injection detected: The definition "security.authentication.provider.dao.main" references the service "security.user_checker" which belongs to a narrower scope. Generally, it is safer to either move "security.authentication.provider.dao.main" to scope "request" or alternatively rely on the provider pattern by injecting the container itself, and requesting the service "security.user_checker" each time it is needed. In rare, special cases however that might not be necessary, then you can set the reference to strict=false to get rid of this error

添加public:true似乎没有什么区别。另外,我不知道这些公共内容真正意味着什么,也许是一个安全问题? public一词总是吓人的=)

1 个答案:

答案 0 :(得分:0)

而不是扩展&#34; OriginalUserChecker&#34;您可以覆盖security.user_checker服务的类,以便能够将request_stack作为参数注入,然后在UserChecker类中检索它,就像这个简单的例子一样:

<强> service.xml中

// Symfony >=2.6

<service id="security.user_checker"
         class="Your\Bundle\Path\ToYour\UserCheckerClass">
    <argument type="service" id="request_stack"/>
</service>

// Symfony <2.6

<service id="security.user_checker"
         class="Your\Bundle\Path\ToYour\UserCheckerClass">
    <argument type="service" id="request" public="true" scope="request"/>
</service>

<强> UserCheckerClass

use Symfony\Component\Security\Core\User\UserCheckerInterface;
// Symfony >=2.6
use Symfony\Component\HttpFoundation\RequestStack;
// Symfony <2.6
use Symfony\Component\HttpFoundation\Request;

class UserChecker implements UserCheckerInterface
{
    private $request;

    public function __construct(
        // Symfony >=2.6
        RequestStack $request
        // Symfony <2.6
        Request $request
    ) {
        $this->request = $request;
    }

    public function checkPreAuth(UserInterface $user)
    {
        // your checks here
    }

    public function checkPostAuth(UserInterface $user)
    {
        // your checks here
    }
}