Аутентификация в функциональных тестах в Symfony 2.1

В настоящее время я переношу проект 2.0. * На текущую версию 2.1 Symfony.

В моих функциональных тестах я в настоящее время имею этот код для создания клиента с аутентификацией:

$client = // create a normal test client $role = 'ROLE_USER'; $firewallName = 'main'; $user = // pull a user from db $client->getCookieJar()->set(new \Symfony\Component\BrowserKit\Cookie(session_name(), true)); $token = new UsernamePasswordToken($user, null, $firewallName, array($role)); self::$kernel->getContainer()->get('session')->set('_security_' . $firewallName, serialize($token)); 

это работает как ожидается в 2.0. *, но не в 2.1, данные не будут установлены в сеансе.

Есть идеи?

Изменить (добавление дополнительной информации):

кажется, что проблема заключается в файле « Symfony \ Component \ Security \ Http \ Firewall \ ContextListener » в методе « onKernelResponse ». Существует этот код:

 if ((null === $token = $this->context->getToken()) || ($token instanceof AnonymousToken)) { $session->remove('_security_'.$this->contextKey); } else { $session->set('_security_'.$this->contextKey, serialize($token)); } 

в моем случае, если «$ token instanceof AnonymousToken» является истинным, и из-за этого ключ сеанса удаляется. если я прокомментирую этот код, все работает так, как ожидалось.

Поэтому, я думаю, мой новый вопрос: что я могу сделать, чтобы маркер не был анонимным?

Правильный способ аутентификации пользователя:

 $firewallName = 'your-firewall-name'; $container = self::$kernel->getContainer() $token = new UsernamePasswordToken($user, null, $firewallName, $user->getRoles()); $container->get('security.context')->setToken($token); 

и аутентификация межсетевого экрана:

 $session = $container->get('session'); $session->set('_security_'.$firewallName, serialize($token)); $session->save(); 

Я зарегистрировал билет по адресу : https://github.com/symfony/symfony/issues/3287

По-видимому, существует проблема с Symfony 2.1 RC.

В моем testuite (работает с 2.0 и теперь 2.1) я использую базовый класс WebTestCase, который расширяет класс Symfony2 WebTestCase.

У меня есть две функции, которые создают анонимный клиент или зарегистрированный в моих тестах:

 static protected function createClient(array $options = array(), array $server = array()) { $client = parent::createClient($options, $server); self::$container = self::$kernel->getContainer(); return $client; } protected function createAuthClient($user, $pass) { return self::createClient(array(), array( 'PHP_AUTH_USER' => $user, 'PHP_AUTH_PW' => $pass, )); } 

Затем в моих тестовых классах я использую:

  $client = static::createClient(); 

для создания анонимного клиента и

  $client = static::createAuthClient('user','pass'); 

для создания аутентифицированного.

Это работает как шарм 2.1

Я могу предложить другое решение (таким образом, он работает для меня). У меня есть собственный поставщик проверки подлинности, со сложной логикой, и я не могу использовать http_basic mechanic вообще.

Вам нужно создать специальное действие, подобное этому

  //TestAuthController.php public function authTestAction(Request $request) { // you can add different security checks as you wish $user_id = $request->query->get("id"); // find user by $user_id using service or user provider service from firewall config $token = new UsernamePasswordToken($user, null, $firewallName, array($role)); // or another authenticated token $this->container->get('security.context')->setToken($token); } 

добавьте routing_test.yml и подключите его так же, как routing_dev.yml

Важно, что этот путь аутентификации должен существовать только в тестовой среде по соображениям безопасности.

  //app/config/routing_test.yml // ... the same routes as in routing_dev.yml _testauth: pattern: /__test defaults: { _controller: MyBundle:TestAuth:authTest } 

Затем в тесте просто отправьте клиент на этот URL-адрес

 public function testSomething() { $client = static::createClient(); $client->request('GET','/__test',array('id'=>146)); $this->assertTrue($client->getContainer()->get('security.context')->isGranted('ROLE_USER')) //it will pass; } 

У меня была та же проблема и я нашел решение во время отладки. В зависимости от вашего хранилища сеансов вам может потребоваться изменить ваш файл cookie с session_name () на «MOCKSESSID» (который используется, если вы используете сеанс mock. Я думаю, что если в вашем файле config_test.yml есть следующее: оно автоматически изменяется на Mock Хранение сеансов:

 framework: test: ~ 

Для полноты, здесь мой полный код (я использую FOS / UserBundle)

  protected function createAuthorizedClient($username = 'user') { $client = $this->createClient(); //Normal WebTestCase client $userProvider = $this->get('fos_user.user_manager'); $user = $userProvider->loadUserByUsername($username); //$client->getCookieJar()->set(new Cookie(session_name(), true)); $client->getCookieJar()->set(new Cookie('MOCKSESSID', true)); $session = self::$kernel->getContainer()->get('session'); $token = new UsernamePasswordToken($user, null, 'main', $user->getRoles()); $client->getContainer()->get('security.context')->setToken($token); $session->set('_security_main', serialize($token)); return $client; }