在功能测试中使用令牌模拟身份验证时如何正确设置用户名
How to properly set the username when simulating authentication with a token in a functional test
我需要编写一个功能测试来测试每个角色是否可以正确访问页面。
为了做到这一点,我是 simulating authentication with a token,但我稍微编辑了 logIn 方法,只是为了用自定义 $username
、$role
和 [=15= 调用它]:
protected function logIn($username, $role, $firewall)
{
$session = $this->client->getContainer()->get('session');
$token = new UsernamePasswordToken($username, null, $firewall, $role);
$session->set('_security_' . $firewall, serialize($token));
$session->save();
$cookie = new Cookie($session->getName(), $session->getId());
$this->client->getCookieJar()->set($cookie);
}
所以我可以调用它来指定哪些角色应该拥有假用户:
$this->logIn('my_username@example.com', ['ROLE_USER'], "my_firewall");
然后我可以测试是否允许或不允许用户访问某些路由:
// check if the access is correctly denied to the ROLE_USER
$this->client->request('GET', '/route-not-allowed-to-user');
$this->assertEquals(403, $this->client->getResponse()->getStatusCode());
// check if the access is correctly allowed to the ROLE_USER
$this->client->request('GET', '/route-allowed-to-user');
$this->assertNotEquals(403, $this->client->getResponse()->getStatusCode());
这些断言有效,唯一的问题是 route-allowed-to-user
我正在使用 twig 输出用户名:
{{ app.user.username }}
但是失败了。我得到状态代码 500
而不是 200
,并且出现以下错误:
Impossible to access an attribute ("username") on a null variable ...
因为app.user
没有设置。
模拟token认证时如何正确设置用户?
我认为发生这种情况是因为您没有通过身份验证过程,只是创建了用户令牌,它没有触发存储用户用户名、角色等的 Symfony 事件。
我最近做了类似的事情,实际上是通过登录表单、填写数据并发送。就像我在进行真正的登录尝试一样,效果很好。
use Symfony\Component\DependencyInjection\ContainerInterface;
abstract class AuthenticatedTestCase extends KernelTestCase
{
static protected $client;
static public function setUpBeforeClass()
{
parent::setUpBeforeClass();
self::$client = static::$kernel->getContainer()->get('test.client');
}
static public function login($login, $password)
{
$crawler = self::$client->request('GET', '/test_admin/login');
$form = $crawler->filter('input[type="submit"]')->form([
'_username' => $login,
'_password' => $password,
]);
self::$client->submit($form);
// Redirect after successful login
self::assertEquals(302, self::$client->getResponse()->getStatusCode());
self::$client->followRedirect();
if (200 === self::$client->getResponse()->getStatusCode()) {
// Redirected URL is OK
// ...
}
}
}
我通过如下编辑 logIn
方法解决了问题:
protected function logIn($username, $password, $firewall)
{
$session = $this->client->getContainer()->get('session');
$authenticationManager = $this->client->getContainer()->get('security.authentication.manager');
$token = $authenticationManager->authenticate(
new UsernamePasswordToken(
$username,
$password,
$firewall
)
);
$session->set('_security_' . $firewall, serialize($token));
$session->save();
$cookie = new Cookie($session->getName(), $session->getId());
$this->client->getCookieJar()->set($cookie);
}
并使用 doctrine data fixtures 来设置用户和角色。
我需要编写一个功能测试来测试每个角色是否可以正确访问页面。
为了做到这一点,我是 simulating authentication with a token,但我稍微编辑了 logIn 方法,只是为了用自定义 $username
、$role
和 [=15= 调用它]:
protected function logIn($username, $role, $firewall)
{
$session = $this->client->getContainer()->get('session');
$token = new UsernamePasswordToken($username, null, $firewall, $role);
$session->set('_security_' . $firewall, serialize($token));
$session->save();
$cookie = new Cookie($session->getName(), $session->getId());
$this->client->getCookieJar()->set($cookie);
}
所以我可以调用它来指定哪些角色应该拥有假用户:
$this->logIn('my_username@example.com', ['ROLE_USER'], "my_firewall");
然后我可以测试是否允许或不允许用户访问某些路由:
// check if the access is correctly denied to the ROLE_USER
$this->client->request('GET', '/route-not-allowed-to-user');
$this->assertEquals(403, $this->client->getResponse()->getStatusCode());
// check if the access is correctly allowed to the ROLE_USER
$this->client->request('GET', '/route-allowed-to-user');
$this->assertNotEquals(403, $this->client->getResponse()->getStatusCode());
这些断言有效,唯一的问题是 route-allowed-to-user
我正在使用 twig 输出用户名:
{{ app.user.username }}
但是失败了。我得到状态代码 500
而不是 200
,并且出现以下错误:
Impossible to access an attribute ("username") on a null variable ...
因为app.user
没有设置。
模拟token认证时如何正确设置用户?
我认为发生这种情况是因为您没有通过身份验证过程,只是创建了用户令牌,它没有触发存储用户用户名、角色等的 Symfony 事件。
我最近做了类似的事情,实际上是通过登录表单、填写数据并发送。就像我在进行真正的登录尝试一样,效果很好。
use Symfony\Component\DependencyInjection\ContainerInterface;
abstract class AuthenticatedTestCase extends KernelTestCase
{
static protected $client;
static public function setUpBeforeClass()
{
parent::setUpBeforeClass();
self::$client = static::$kernel->getContainer()->get('test.client');
}
static public function login($login, $password)
{
$crawler = self::$client->request('GET', '/test_admin/login');
$form = $crawler->filter('input[type="submit"]')->form([
'_username' => $login,
'_password' => $password,
]);
self::$client->submit($form);
// Redirect after successful login
self::assertEquals(302, self::$client->getResponse()->getStatusCode());
self::$client->followRedirect();
if (200 === self::$client->getResponse()->getStatusCode()) {
// Redirected URL is OK
// ...
}
}
}
我通过如下编辑 logIn
方法解决了问题:
protected function logIn($username, $password, $firewall)
{
$session = $this->client->getContainer()->get('session');
$authenticationManager = $this->client->getContainer()->get('security.authentication.manager');
$token = $authenticationManager->authenticate(
new UsernamePasswordToken(
$username,
$password,
$firewall
)
);
$session->set('_security_' . $firewall, serialize($token));
$session->save();
$cookie = new Cookie($session->getName(), $session->getId());
$this->client->getCookieJar()->set($cookie);
}
并使用 doctrine data fixtures 来设置用户和角色。