Authentication in functional tests in Symfony 2.1

后端 未结 5 727
梦谈多话
梦谈多话 2020-12-13 05:15

I am currently in the process of migrating a 2.0.* project to the current 2.1 beta of Symfony.

In my functional tests i currently have this code to create a client w

相关标签:
5条回答
  • 2020-12-13 05:29

    I've logged a ticket on: https://github.com/symfony/symfony/issues/3287

    There appears to be an existing issue with Symfony 2.1 RC.

    0 讨论(0)
  • 2020-12-13 05:32

    i had the same issue and found a solution while debugging. Depending on your Session Storage, you might have to change your cookie from session_name() to 'MOCKSESSID' (which is used if your using the mock session. I think if you have the following in your config_test.yml it is automatically changed to Mock Session Storage:

    framework:
       test: ~
    

    For completeness, here my full code (i'm using 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;
    }
    
    0 讨论(0)
  • 2020-12-13 05:34

    In my testsuite (working on 2.0 and now 2.1) I use a Base class WebTestCase that extends the Symfony2 WebTestCase class.

    I have these two functions that create an anonymous client or a logged one in my tests:

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

    Then, in my Test classes, I use:

        $client = static::createClient();
    

    to create an anon client and

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

    to create an authenticated one.

    This works like a charm on 2.1

    0 讨论(0)
  • 2020-12-13 05:35

    I can suggest another solution (thus it working for me). I have an custom authentication provider, with complicated logic and I can't use http_basic mechanic at all.

    You need to create special Action like this

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

    add routing_test.yml and plug it just as routing_dev.yml

    Important thing that this authentication route must exists only in test enviroment, for security reasons.

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

    Then in test just send client to this 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;
    }
    
    0 讨论(0)
  • 2020-12-13 05:47

    Proper way to authenticate user is:

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

    and firewall authentication:

    $session = $container->get('session');
    $session->set('_security_'.$firewallName, serialize($token));
    $session->save();
    
    0 讨论(0)
提交回复
热议问题