Я пытаюсь запустить простой тест аутентификации, используя PHPUnit с Symfony 4, чтобы проверить, успешно ли пользователь вошел в систему. Я выполнил документацию для запуска теста аутентификации. Страница /admin
будет автоматически перенаправлена на /login
, если пользователь не вошел в систему.
Я получаю эту ошибку при запуске теста:
There was 1 failure:
1) App\Tests\AuthTest::testAdminPanel
Failed asserting that 302 is identical to 200.
~ конфиг / пакеты / тест / security.yaml:
security:
firewalls:
main:
http_basic: ~
Тест:
public function testAdminPanel() {
$client = static::createClient(array(), array(
'PHP_AUTH_USER' => 'username',
'PHP_AUTH_PW' => 'password',
));
$crawler = $client->request('GET', '/admin');
$this->assertSame(Response::HTTP_OK, $client->getResponse()->getStatusCode());
}
Примечание. Учетная запись username
вместе с паролем password
существуют в базе данных.
Контроллер безопасности:
<?php
namespace App\Security;
use App\Form\LoginFormType;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoder;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
/**
* Class LoginFormAuthenticator
* @package App\Security
*/
class LoginFormAuthenticator extends AbstractGuardAuthenticator
{
/**
* @var FormFactoryInterface
*/
private $formFactory;
/**
* @var EntityManager
*/
private $em;
/**
* @var RouterInterface
*/
private $router;
/**
* @var UserPasswordEncoder
*/
private $userPasswordEncoder;
/**
* LoginFormAuthenticator constructor.
* @param FormFactoryInterface $formFactory
* @param EntityManagerInterface $em
* @param RouterInterface $router
* @param UserPasswordEncoderInterface $userPasswordEncoder
*/
public function __construct(FormFactoryInterface $formFactory, EntityManagerInterface $em, RouterInterface $router, UserPasswordEncoderInterface $userPasswordEncoder)
{
$this->formFactory = $formFactory;
$this->em = $em;
$this->router = $router;
$this->userPasswordEncoder = $userPasswordEncoder;
}
/**
* @return string
*/
protected function getLoginUrl()
{
return $this->router->generate('login');
}
/**
* @param Request $request
* @return bool
*
* Called on every request to decide if this authenticator should be
* used for the request. Returning false will cause this authenticator
* to be skipped. Current implementation checks that this request method is POST and
* that the user is on the login page.
*
*/
public function supports(Request $request)
{
return ($request->attributes->get('_route') === 'login' && $request->isMethod('POST'));
}
/**
* @param Request $request
* @param AuthenticationException|null $authException
* @return RedirectResponse|Response
*/
public function start(Request $request, AuthenticationException $authException = null)
{
return new RedirectResponse($this->router->generate('login'));
}
/**
* @param Request $request
* @return bool|mixed
*/
public function getCredentials(Request $request)
{
$form = $this->formFactory->create(LoginFormType::class);
$form->handleRequest($request);
$data = $form->getData();
$request->getSession()->set(
Security::LAST_USERNAME,
$data['username']
);
return $data;
}
/**
* @param mixed $credentials
* @param UserProviderInterface $userProvider
* @return null|object|UserInterface
*/
public function getUser($credentials, UserProviderInterface $userProvider)
{
$username = $credentials['username'];
$user = $this->em->getRepository('App:User')->findOneBy(['username' => $username]);
if(empty($user)) {
$user = $this->em->getRepository('App:User')->findOneBy(array('email' => $username));
}
return $user;
}
/**
* @param mixed $credentials
* @param UserInterface $user
* @return bool
*/
public function checkCredentials($credentials, UserInterface $user)
{
$password = $credentials['password'];
if($this->userPasswordEncoder->isPasswordValid($user, $password)) {
return true;
}
return false;
}
/**
* @return string
*/
public function getDefaultSuccessRedirectUrl()
{
return $this->router->generate('default');
}
/**
* @param Request $request
* @param AuthenticationException $exception
* @return RedirectResponse
*/
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
$request->getSession()->set(Security::AUTHENTICATION_ERROR, $exception);
return new RedirectResponse($this->router->generate('login'));
}
/**
* @param Request $request
* @param TokenInterface $token
* @param string $providerKey
* @return null|RedirectResponse|Response
* @throws \Doctrine\ORM\ORMException
* @throws \Doctrine\ORM\OptimisticLockException
*/
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
$user = $token->getUser();
$user->setLastLogin(new \DateTime('now'));
$this->em->persist($user);
$this->em->flush();
return new RedirectResponse($this->router->generate('easyadmin'));
}
/**
* @return bool
*/
public function supportsRememberMe()
{
return false;
}
}