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

Mat*_*der 5 php authentication symfony fosuserbundle

我将 Synfony2 与 FOSUserBundle 一起使用,并且我有一个自定义 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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

public function checkPostAuth(UserInterface $user, Request $request)
Run Code Online (Sandbox Code Playgroud)

错误说我的覆盖必须符合原始/界面。

尝试像在控制器中一样获取请求

$this->container->get('request_stack')->getCurrentRequest();
Run Code Online (Sandbox Code Playgroud)

或者像这样

$currentHost = $request->getHost();
Run Code Online (Sandbox Code Playgroud)

或者像这样

$cont = $this->getContainer();
Run Code Online (Sandbox Code Playgroud)

或者像这样

$request = $this->getRequest();
Run Code Online (Sandbox Code Playgroud)

或者像这样

$request = $container->get('request');
Run Code Online (Sandbox Code Playgroud)

但运气不好 =) 我不是 Symfony2 大师,正如你所知,我只是凭空猜测 =)


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

services:
    security.user_checker:
        class: BizTV\UserBundle\Controller\UserCheckerNew
        arguments: [ "@request" ]
        scope: request
        public: true
Run Code Online (Sandbox Code Playgroud)

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

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.'
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

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

gp_*_*ver 0

您可以重写该security.user_checker服务,以便能够注入request_stackas 参数,然后在您的UserChecker类中检索它,而不是扩展“OriginalUserChecker”类,如下简单示例:

服务.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>
Run Code Online (Sandbox Code Playgroud)

用户检查类

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
    }
}
Run Code Online (Sandbox Code Playgroud)