我目前在迁移2.0的过程。*项目的Symfony目前2.1测试版。
在我的功能测试,我现在有这样的代码来创建一个客户端身份验证:
$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,该数据不会在会话中设置。
有任何想法吗?
编辑(添加详细信息):
看来,问题出在方法“onKernelResponse”文件“ 的Symfony \分量\安全\ HTTP \防火墙\ ContextListener”的。 有这样的代码:
if ((null === $token = $this->context->getToken()) || ($token instanceof AnonymousToken)) {
$session->remove('_security_'.$this->contextKey);
} else {
$session->set('_security_'.$this->contextKey, serialize($token));
}
在我的情况下,如果“$令牌的instanceof AnonymousToken”是真实的,因为会话密钥被删除的。 如果我注释掉的代码一切正常。
所以我想我的新问题是:我能做些什么使令牌不是匿名?
Answer 1:
验证用户正确的方法是:
$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();
Answer 2:
我登录了票上: https://github.com/symfony/symfony/issues/3287
似乎有与Symfony的2.1 RC的现有问题。
Answer 3:
在我的测试套件(工作2.0和2.1现在)我使用扩展的Symfony2 WebTestCase类的基类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的魅力
Answer 4:
我可以建议另一种解决方案(从而为我工作)。 我有一个自定义身份验证提供商,拥有复杂的逻辑,我不能在所有使用http_basic技工。
您需要创建这样的专项行动
//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 }
然后,在测试只是给客户这个网址
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;
}
Answer 5:
我有同样的问题,并找到了解决方案,同时调试。 根据您的会话存储,您可能需要您的Cookie从会话名称()为“MOCKSESSID”(这是如果你的使用模拟会话中使用而改变。我认为,如果你已经在你的config_test.yml以下则自动变为模拟会话存储:
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;
}
文章来源: Authentication in functional tests in Symfony 2.1