php symfony symfony-2.1

php - Autenticación en pruebas funcionales en Symfony 2.1



symfony-2.1 (5)

En mi testinguite (trabajando en 2.0 y ahora 2.1) uso una clase Base WebTestCase que extiende la clase Symfony2 WebTestCase.

Tengo estas dos funciones que crean un cliente anónimo o uno registrado en mis pruebas:

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, )); }

Luego, en mis clases de prueba, uso:

$client = static::createClient();

para crear un cliente anon y

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

Para crear uno autenticado.

Esto funciona como un encanto en 2.1

Actualmente estoy en el proceso de migrar un proyecto 2.0. * A la actual versión beta 2.1 de Symfony.

En mis pruebas funcionales actualmente tengo este código para crear un cliente con autenticación:

$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));

esto funciona como se esperaba en 2.0. * pero no en 2.1, los datos no se configuran en la sesión.

¿Algunas ideas?

Editar (añadiendo más información):

Parece que el problema está en el archivo " Symfony / Component / Security / Http / Firewall / ContextListener " en el método " onKernelResponse ". Hay este código:

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

en mi caso el if "$ token instanceof AnonymousToken" es verdadero, y debido a eso se elimina la clave de sesión. Si comento ese código todo funciona como se espera.

Así que supongo que mi nueva pregunta es: ¿Qué puedo hacer para que el token no sea anónimo?



La forma correcta de autenticar al usuario es:

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

y autenticación de firewall:

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


Puedo sugerir otra solución (por lo que funciona para mí). Tengo un proveedor de autenticación personalizado, con lógica complicada y no puedo usar la mecánica http_basic en absoluto.

Necesitas crear una acción especial como esta.

//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); }

agregue routing_test.yml y conéctelo como routing_dev.yml

Lo importante es que esta ruta de autenticación debe existir solo en el entorno de prueba, por razones de seguridad.

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

Luego, en la prueba, simplemente envíe al cliente a esta 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; }


Tuve el mismo problema y encontré una solución al depurar. Dependiendo de su almacenamiento de sesión, es posible que tenga que cambiar su cookie de session_name () a ''MOCKSESSID'' (que se usa si usa la sesión simulada. Creo que si tiene lo siguiente en su config_test.yml, se cambia automáticamente a Mock Almacenamiento de sesión:

framework: test: ~

Para completar, aquí mi código completo (estoy usando 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; }