簡體   English   中英

如何在Symfony 2.3中的功能測試中登錄會話中的用戶?

[英]How to log in User in Session within a Functional Test in Symfony 2.3?

我已經在stackoverflow上閱讀了很多關於此的帖子。 但是大多數方法在Symfony 2.3中沒用。 所以我嘗試在測試中手動登錄用戶以在后端進行一些操作。 這是我的security.yml

security:
...
  role_hierarchy:
        ROLE_SILVER: [ROLE_BRONZE]
        ROLE_GOLD: [ROLE_BRONZE, ROLE_SILVER]
        ROLE_PLATINUM: [ROLE_BRONZE, ROLE_SILVER, ROLE_GOLD]
        ROLE_ADMIN: [ROLE_BRONZE, ROLE_SILVER, ROLE_GOLD, ROLE_PLATINUM, ROLE_ALLOWED_TO_SWITCH]

    providers:
        database:
            entity: { class: Fox\PersonBundle\Entity\Person, property: username }

    firewalls:
        dev:
            pattern:  ^/(_(profiler|wdt)|css|images|js)/
            security: false

        login:
            pattern:  ^/person/login$
            security: false

        main:
            pattern:    ^/
            provider:   database
            form_login:
                check_path: /person/login-check
                login_path: /person/login
                default_target_path: /person/view
                always_use_default_target_path: true
            logout:
                path:   /person/logout
                target: /
            anonymous: true

    access_control:
        - { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/person/registration, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/person, roles: ROLE_BRONZE }

這是我的測試:

class ProfileControllerTest extends WebTestCase
{
    public function setUp()
    {
        $kernel = self::getKernelClass();

        self::$kernel = new $kernel('dev', true);
        self::$kernel->boot();
    }

    public function testView()
    {
        $client = static::createClient();

        $person = self::$kernel->getContainer()->get('doctrine')->getRepository('FoxPersonBundle:Person')->findOneByUsername('master');

        $token = new UsernamePasswordToken($person, $person->getPassword(), 'main', $person->getRoles());

        self::$kernel->getContainer()->get('security.context')->setToken($token);

        self::$kernel->getContainer()->get('event_dispatcher')->dispatch(
        AuthenticationEvents::AUTHENTICATION_SUCCESS,
        new AuthenticationEvent($token));

        $crawler = $client->request('GET', '/person/view');
    }

當我運行此測試時, $person = $this->get(security.context)->getToken()->getUser(); 方法不適用於測試Controller。 如果在控制器中調用$person->getId(); 我將有一個錯誤Call to a member function getId() on a non-object in...

那么你能告訴在Symfony 2.3中使用功能測試登錄用戶的正確方法嗎?

謝謝!

EDIT_1 :如果我更改Symfony/Component/Security/Http/Firewall/ContextListener.php並注釋一個字符串:

if (null === $session || null === $token = $session->get('_security_'.$this->contextKey)) {
            // $this->context->setToken(null);

            return;
        }

所有測試都沒有錯誤。

EDIT_2:這是我已經嘗試使用參考: 第一 第二 第三 第四 第五 第六 第七 第八 第九

最后我解決了! 這是工作代碼的示例:

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\BrowserKit\Cookie;

class ProfileControllerTest extends WebTestCase
{
    protected function createAuthorizedClient()
    {
        $client = static::createClient();
        $container = static::$kernel->getContainer();
        $session = $container->get('session');
        $person = self::$kernel->getContainer()->get('doctrine')->getRepository('FoxPersonBundle:Person')->findOneByUsername('master');

        $token = new UsernamePasswordToken($person, null, 'main', $person->getRoles());
        $session->set('_security_main', serialize($token));
        $session->save();

        $client->getCookieJar()->set(new Cookie($session->getName(), $session->getId()));

        return $client;
    }

    public function testView()
    {
        $client = $this->createAuthorizedClient();
        $crawler = $client->request('GET', '/person/view');
        $this->assertEquals(
            200,
            $client->getResponse()->getStatusCode()
        );
    }   

希望它有助於節省您的時間和神經;)

作為已接受解決方案的補充,我將展示我在控制器中 登錄用戶的功能。

// <!-- Symfony 2.4 --> //

use Symfony\Component\Security\Core\AuthenticationEvents;
use Symfony\Component\Security\Core\Event\AuthenticationEvent;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;

private function loginUser(UsernamePasswordToken $token, Request $request)     {
    $this->get('security.context')->setToken($token);

    $s = $this->get('session');
    $s->set('_security_main', serialize($token)); // `main` is firewall name
    $s->save();

    $ed = $this->get('event_dispatcher');

    $ed->dispatch(
        AuthenticationEvents::AUTHENTICATION_SUCCESS,
        new AuthenticationEvent($token)
    );

    $ed->dispatch(
        "security.interactive_login",
        new InteractiveLoginEvent($request, $token)
    );
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM