8000 Tweaks · symfony/symfony-docs@a9f63e3 · GitHub
[go: up one dir, main page]

Skip to content

Commit a9f63e3

Browse files
committed
Tweaks
1 parent 8649d07 commit a9f63e3

File tree

3 files changed

+138
-1
lines changed

3 files changed

+138
-1
lines changed

_build/redirection_map

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,4 +480,3 @@
480480
/components/translation/custom_formats https://github.com/symfony/translation
481481
/components/translation/custom_message_formatter https://github.com/symfony/translation
482482
/components/notifier https://github.com/symfony/notifier
483-
/testing/http_authentication /testing

testing.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,8 @@ command.
567567
If the information you need to check is available from the profiler, use
568568
it instead.
569569

570+
.. _testing_logging_in_users:
571+
570572
Logging in Users (Authentication)
571573
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
572574

testing/http_authentication.rst

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
.. index::
2+
single: Tests; HTTP authentication
3+
4+
How to Simulate HTTP Authentication in a Functional Test
5+
========================================================
6+
7+
.. caution::
8+
9+
Starting from Symfony 5.1, the methods explained in this article are no
10+
longer recommended to logging in users in your tests. Instead, use
11+
:ref:`the loginUser() method <testing_logging_in_users>`.
12+
13+
Authenticating requests in functional tests can slow down the entire test suite.
14+
This could become an issue especially when the tests reproduce the same steps
15+
that users follow to authenticate, such as submitting a login form or using
16+
OAuth authentication services.
17+
18+
This article explains the two most popular techniques to avoid these issues and
19+
create fast tests when using authentication.
20+
21+
Using a Faster Authentication Mechanism Only for Tests
22+
------------------------------------------------------
23+
24+
When your application is using a ``form_login`` authentication, you can make
25+
your tests faster by allowing them to use HTTP authentication. This way your
26+
tests authenticate with the simple and fast HTTP Basic method whilst your real
27+
users still log in via the normal login form.
28+
29+
The trick is to use the ``http_basic`` authentication in your application
30+
firewall, but only in the configuration file used by tests:
31+
32+
.. configuration-block::
33+
34+
.. code-block:: yaml
35+
36+
# config/packages/test/security.yaml
37+
security:
38+
firewalls:
39+
# replace 'main' by the name of your own firewall
40+
main:
41+
http_basic: ~
42+
43+
.. code-block:: xml
44+
45+
<!-- config/packages/test/security.xml -->
46+
<security:config>
47+
<!-- replace 'main' by the name of your own firewall -->
48+
<security:firewall name="main">
49+
<security:http-basic/>
50+
</security:firewall>
51+
</security:config>
52+
53+
.. code-block:: php
54+
55+
// config/packages/test/security.php
56+
$container->loadFromExtension('security', [
57+
'firewalls' => [
58+
// replace 'main' by the name of your own firewall
59+
'main' => [
60+
'http_basic' => [],
61+
],
62+
],
63+
]);
64+
65+
Tests can now authenticate via HTTP passing the username and password as server
66+
variables using the second argument of ``createClient()``::
67+
68+
$client = static::createClient([], [
69+
'PHP_AUTH_USER' => 'username',
70+
'PHP_AUTH_PW' => 'pa$$word',
71+
]);
72+
73+
The username and password can also be passed on a per request basis::
74+
75+
$client->request('DELETE', '/post/12', [], [], [
76+
'PHP_AUTH_USER' => 'username',
77+
'PHP_AUTH_PW' => 'pa$$word',
78+
]);
79+
80+
Creating the Authentication Token
81+
---------------------------------
82+
83+
If your application uses a more advanced authentication mechanism, you can't
84+
use the previous trick, 6D40 but it's still possible to make tests faster. The trick
85+
now is to bypass the authentication process, create the *authentication token*
86+
yourself and store it in the session.
87+
88+
This technique requires some knowledge of the Security component internals,
89+
but the following example shows a complete example that you can adapt to your
90+
needs::
91+
92+
// tests/Controller/DefaultControllerTest.php
93+
namespace App\Tests\Controller;
94+
95+
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
96+
use Symfony\Component\BrowserKit\Cookie;
97+
use Symfony\Component\HttpFoundation\Response;
98+
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
99+
100+
class DefaultControllerTest extends WebTestCase
101+
{
102+
private $client = null;
103+
104+
public function setUp()
105+
{
106+
$this->client = static::createClient();
107+
}
108+
109+
public function testSecuredHello()
110+
{
111+
$this->logIn();
112+
$crawler = $this->client->request('GET', '/admin');
113+
114+
$this->assertSame(Response::HTTP_OK, $this->client->getResponse()->getStatusCode());
115+
$this->assertSame('Admin Dashboard', $crawler->filter('h1')->text());
116+
}
117+
118+
private function logIn()
119+
{
120+
$session = self::$container->get('session');
121+
122+
$firewallName = 'secure_area';
123+
// if you don't define multiple connected firewalls, the context defaults to the firewall name
124+
// See https://symfony.com/doc/current/reference/configuration/security.html#firewall-context
125+
$firewallContext = 'secured_area';
126+
127+
// you may need to use a different token class depending on your application.
128+
// for example, when using Guard authentication you must instantiate PostAuthenticationGuardToken
129+
$token = new UsernamePasswordToken('admin', null, $firewallName, ['ROLE_ADMIN']);
130+
$session->set('_security_'.$firewallContext, serialize($token));
131+
$session->save();
132+
133+
$cookie = new Cookie($session->getName(), $session->getId());
134+
$this->client->getCookieJar()->set($cookie);
135+
}
136+
}

0 commit comments

Comments
 (0)
0