Symfony2的。部署在托管之后,简单的preauth无法正常工作,因为它在成功身份验证后尝试再次进行身份验证

时间:2016-02-28 10:13:42

标签: symfony authentication

在我的Symfony应用程序中,我有两个防火墙:

main:
    pattern: ^/(?!login).+
    stateless: true
    simple_preauth:
        authenticator: app_bundle.api_key_authenticator
    provider: api_key_user_provider
    anonymous: ~
    logout: ~

login:
    pattern: ^/login$
    stateless: false
    simple_preauth:
        authenticator: app_bundle.email_password_authenticator
    provider: email_user_provider
    anonymous: ~
    logout: ~

通过/ login进行身份验证后,用户获取apiKey,允许访问app的另一部分。

在我的本地服务器上一切正常。但在部署托管身份验证后无法正常工作。

调试后我看到,该电子邮件验证器尝试进行两次身份验证。 所以第一次它返回正确的令牌,但第二次它返回NULL,因为loadUserByUsername()方法获取用户名而不是电子邮件(只能通过电子邮件进行身份验证)。

这是我的电子邮件验证员:

<?php

namespace AppBundle\Security\Authentication;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Authentication\SimplePreAuthenticatorInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;

class EmailPasswordAuthenticator implements SimplePreAuthenticatorInterface
{
    private $encoder;

    public function __construct(UserPasswordEncoderInterface $encoder)
    {
        $this->encoder = $encoder;
    }

    public function createToken(Request $request, $providerKey)
    {
        if ($request->get('email') && $request->get('password')) {
            return new UsernamePasswordToken(
                $request->get('email'), 
                $request->get('password'), 
                $providerKey
            );
        }

        throw new AuthenticationException('Authentication failed');
    }

    public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey)
    {
        try {
            $user = $userProvider->loadUserByUsername($token->getUsername());
        } catch (UsernameNotFoundException $e) {
            throw new AuthenticationException('Invalid username or password');
        }

        $passwordValid = $this->encoder->isPasswordValid($user, $token->getCredentials());

        if ($passwordValid) {
            return new UsernamePasswordToken(
                $user,
                $user->getPassword(),
                $providerKey,
                $user->getRoles()
            );
        }

        throw new AuthenticationException('Password incorrect');
    }

    public function supportsToken(TokenInterface $token, $providerKey)
    {
        return $token instanceof UsernamePasswordToken 
            && $token->getProviderKey() === $providerKey;
    }

}

这是我的用户提供商:

<?php

namespace AppBundle\Security\User;

use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use AppBundle\Repository\UserRepository;
use Symfony\Component\Security\Core\User\UserInterface;

class EmailUserProvider implements UserProviderInterface
{
    public function __construct(UserRepository $userRepository)
    {
        $this->userRepository = $userRepository;
    }

    public function loadUserByUsername($email)
    {
        $user = $this->userRepository->findOneBy(array('email' => $email));

        if (null === $user) {
            throw new UsernameNotFoundException(
                sprintf(
                    'User with email "%s" not found',
                    $email
                )
            );
        }

        return $user;
    }

    public function refreshUser(UserInterface $user)
    {
        return $this->loadUserByUsername($user->getEmail());
    }

    public function supportsClass($class)
    {
        return $class === 'AppBundle\Entity\User';
    }

}

请帮助我理解,发生了什么。这种奇怪的行为可能是什么原因?

非常感谢您的帮助!

UPD 即可。我可以看到,authenticate()方法第一次调用Symfony\Component\Security\Http\Firewall\SimplePreAuthenticationListener,第二次调用Symfony\Component\Security\Http\Firewall\AccessListener

这部分代码存在问题:

// AccessListener
if (!$token->isAuthenticated()) {
    $token = $this->authManager->authenticate($token);
    $this->tokenStorage->setToken($token);
}

1 个答案:

答案 0 :(得分:0)

解决。问题出现在我的组和角色表中,它们是空的,没有来自它们的数据用户无法进行身份验证。