我已经在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 : 这是我试图使用的参考: first second third fourth fifth sixth seventh eighth nineth
答案 0 :(得分:11)
最终我解决了!这是工作代码的示例:
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()
);
}
希望有助于节省您的时间和精力;)
答案 1 :(得分:1)
作为已接受解决方案的补充,我将向登录用户在控制器中显示我的功能。
// <!-- 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)
);
}