@@ -6,143 +6,12 @@ How to Simulate HTTP Authentication in a Functional Test
6
6
7
7
.. caution ::
8
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 >` .
9
+ Starting from Symfony 5.1, a `` loginUser() `` method was introduced to
10
+ ease testing secured applications. See :ref: ` testing_logging_in_users `
11
+ for more information about this .
12
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.
13
+ If you are still using an older version of Symfony, view
14
+ `previous versions of this article `_ for information on how to simulate
15
+ HTTP authentication.
17
16
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
- <?xml version =" 1.0" encoding =" UTF-8" ?>
47
- <container xmlns =" http://symfony.com/schema/dic/services"
48
- xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
49
- xmlns : security =" http://symfony.com/schema/dic/security"
50
- xsi : schemaLocation =" http://symfony.com/schema/dic/security
51
- https://symfony.com/schema/dic/security/security-1.0.xsd
52
- http://symfony.com/schema/dic/security
53
- https://symfony.com/schema/dic/security/security-1.0.xsd" >
54
-
55
- <security : config >
56
- <!-- replace 'main' by the name of your own firewall -->
57
- <security : firewall name =" main" >
58
- <security : http-basic />
59
- </security : firewall >
60
- </security : config >
61
-
62
- .. code-block :: php
63
-
64
- // config/packages/test/security.php
65
- $container->loadFromExtension('security', [
66
- 'firewalls' => [
67
- // replace 'main' by the name of your own firewall
68
- 'main' => [
69
- 'http_basic' => [],
70
- ],
71
- ],
72
- ]);
73
-
74
- Tests can now authenticate via HTTP passing the username and password as server
75
- variables using the second argument of ``createClient() ``::
76
-
77
- $client = static::createClient([], [
78
- 'PHP_AUTH_USER' => 'username',
79
- 'PHP_AUTH_PW' => 'pa$$word',
80
- ]);
81
-
82
- The username and password can also be passed on a per request basis::
83
-
84
- $client->request('DELETE', '/post/12', [], [], [
85
- 'PHP_AUTH_USER' => 'username',
86
- 'PHP_AUTH_PW' => 'pa$$word',
87
- ]);
88
-
89
- Creating the Authentication Token
90
- ---------------------------------
91
-
92
- If your application uses a more advanced authentication mechanism, you can't
93
- use the previous trick, but it's still possible to make tests faster. The trick
94
- now is to bypass the authentication process, create the *authentication token *
95
- yourself and store it in the session.
96
-
97
- This technique requires some knowledge of the Security component internals,
98
- but the following example shows a complete example that you can adapt to your
99
- needs::
100
-
101
- // tests/Controller/DefaultControllerTest.php
102
- namespace App\Tests\Controller;
103
-
104
- use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
105
- use Symfony\Component\BrowserKit\Cookie;
106
- use Symfony\Component\HttpFoundation\Response;
107
- use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
108
-
109
- class DefaultControllerTest extends WebTestCase
110
- {
111
- private $client = null;
112
-
113
- public function setUp()
114
- {
115
- $this->client = static::createClient();
116
- }
117
-
118
- public function testSecuredHello()
119
- {
120
- $this->logIn();
121
- $crawler = $this->client->request('GET', '/admin');
122
-
123
- $this->assertSame(Response::HTTP_OK, $this->client->getResponse()->getStatusCode());
124
- $this->assertSame('Admin Dashboard', $crawler->filter('h1')->text());
125
- }
126
-
127
- private function logIn()
128
- {
129
- $session = self::$container->get('session');
130
-
131
- // somehow fetch the user (e.g. using the user repository)
132
- $user = ...;
133
-
134
- $firewallName = 'secure_area';
135
- // if you don't define multiple connected firewalls, the context defaults to the firewall name
136
- // See https://symfony.com/doc/current/reference/configuration/security.html#firewall-context
137
- $firewallContext = 'secured_area';
138
-
139
- // you may need to use a different token class depending on your application.
140
- // for example, when using Guard authentication you must instantiate PostAuthenticationGuardToken
141
- $token = new UsernamePasswordToken($user, null, $firewallName, $user->getRoles());
142
- $session->set('_security_'.$firewallContext, serialize($token));
143
- $session->save();
144
-
145
- $cookie = new Cookie($session->getName(), $session->getId());
146
- $this->client->getCookieJar()->set($cookie);
147
- }
148
- }
17
+ .. _previous versions of this article : https://symfony.com/doc/5.0/testing/http_authentication.html
0 commit comments