Symfony 2.1中的功能测试中的身份验证
我目前正在将2.0。*项目迁移到Symfony当前的2.1测试版。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,该数据不会在会话中设置。
任何想法?
编辑(添加详细信息):
看来问题就出在文件 “的Symfony \分量\安全\ HTTP \防火墙\ ContextListener” 中的方法 “onKernelResponse” 的。有这样的代码:
if ((null === $token = $this->context->getToken()) || ($token instanceof AnonymousToken)) {
$session->remove('_security_'.$this->contextKey);
} else {
$session->set('_security_'.$this->contextKey, serialize($token));
}
在我的情况下,如果“$令牌的instanceof AnonymousToken”是真实的,正因为如此会话密钥被删除。如果我注释掉代码,一切都按预期工作。
所以我想我的新问题是:我能做些什么来使令牌不是匿名的?
验证用户正确的方法是:
$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();
在我的测试套件(工作于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
我可以建议另一种解决方案(因此它为我工作)。我有一个自定义身份验证提供程序,具有复杂的逻辑,我根本无法使用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;
}
这对我有用,而其他方法没有(使用Sf2.3) – caponica 2013-08-23 23:47:17
我有同样的问题,并找到了解决方案,同时调试。根据您的会话存储,您可能必须将cookie从session_name()更改为'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;
}
我使用的是非常相似的片段,以你的登录特定功能测试用户。我也升级到了2.1,并且真的让我很开心,因为我的许多功能测试现在都失败了。 – 2012-08-07 06:05:38
我发现在ContextListener.php中,ac所有的都是$ this-> context-> setToken(null),并且因为$ session === null而被调用?嗯... – 2012-08-07 06:44:22
当我注释掉ContextListener.php:第77行 - $ this-> context-> setToken(null)时,我的测试完美无缺!所以也许这是一个线索! – 2012-08-07 06:49:11