在我的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);
}
答案 0 :(得分:0)
解决。问题出现在我的组和角色表中,它们是空的,没有来自它们的数据用户无法进行身份验证。