Skip to content

Commit c283606

Browse files
committed
Add authentication support to user context subscriber
1 parent e61d360 commit c283606

File tree

3 files changed

+82
-4
lines changed

3 files changed

+82
-4
lines changed

doc/symfony-cache-configuration.rst

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,10 @@ User Context
118118
~~~~~~~~~~~~
119119

120120
To support :doc:`user context hashing <user-context>` you need to register the
121-
``UserContextSubscriber``. If the default settings are right for you, you don't
122-
need to do anything more. You can customize a number of options through the
123-
constructor:
121+
``UserContextSubscriber``. The user context is then automatically recognized
122+
based on session cookies or authorization headers. If the default settings are
123+
right for you, you don't need to do anything more. You can customize a number of
124+
options through the constructor:
124125

125126
* **anonymous_hash**: Hash used for anonymous user. This is a performance
126127
optimization to not do a backend request for users that are not logged in.
@@ -160,6 +161,16 @@ constructor:
160161
user context hash for every users, or not having it cached at all, which
161162
hurts performance.
162163

164+
.. note::
165+
166+
To use authorization headers for user context, you might have to add some server
167+
configuration to make these headers available to PHP.
168+
169+
With Apache, you can do this for example in a ``.htaccess`` file:
170+
171+
RewriteEngine On
172+
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
173+
163174
Cleaning the Cookie Header
164175
^^^^^^^^^^^^^^^^^^^^^^^^^^
165176

src/SymfonyCache/UserContextSubscriber.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,10 @@ protected function cleanupHashLookupRequest(Request $hashLookupRequest, Request
130130
$hashLookupRequest->cookies->set($name, $value);
131131
}
132132
}
133-
$hashLookupRequest->headers->set('Cookie', http_build_query($sessionIds, '', '; '));
133+
134+
if (count($sessionIds) > 0) {
135+
$hashLookupRequest->headers->set('Cookie', http_build_query($sessionIds, '', '; '));
136+
}
134137
}
135138

136139
/**
@@ -180,6 +183,16 @@ private function getUserHash(HttpKernelInterface $kernel, Request $request)
180183
*/
181184
private function isAnonymous(Request $request)
182185
{
186+
// You might have to enable rewriting of the Authorization header in your server config or .htaccess:
187+
// RewriteEngine On
188+
// RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
189+
if ($request->server->has('AUTHORIZATION') ||
190+
$request->server->has('HTTP_AUTHORIZATION') ||
191+
$request->server->has('PHP_AUTH_USER')
192+
) {
193+
return false;
194+
}
195+
183196
foreach ($request->cookies as $name => $value) {
184197
if ($this->isSessionName($name)) {
185198
return false;

tests/Unit/SymfonyCache/UserContextSubscriberTest.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@ public function testUserHashUserWithSession($arg, $options)
132132
$cookieString = "PHPSESSID=$sessionId1; foo=bar; PHPSESSIDsdiuhsdf4535d4f=$sessionId2";
133133
$request = Request::create('/foo', 'GET', array(), $cookies, array(), array('Cookie' => $cookieString));
134134

135+
// Add a cookie which should not be available in the eventual hash request anymore
136+
$request->cookies->set('foo', 'bar');
137+
135138
$hashRequest = Request::create($options['user_hash_uri'], $options['user_hash_method'], array(), array(), array(), $request->server->all());
136139
$hashRequest->attributes->set('internalRequest', true);
137140
$hashRequest->headers->set('Accept', $options['user_hash_accept_header']);
@@ -160,6 +163,7 @@ public function testUserHashUserWithSession($arg, $options)
160163
$request->getMethod();
161164
$request->getPathInfo();
162165
$that->assertEquals($hashRequest, $request);
166+
$that->assertCount(2, $request->cookies->all());
163167

164168
return true;
165169
}),
@@ -177,6 +181,56 @@ public function testUserHashUserWithSession($arg, $options)
177181
$this->assertSame($expectedContextHash, $request->headers->get($options['user_hash_header']));
178182
}
179183

184+
/**
185+
* @dataProvider provideConfigOptions
186+
*/
187+
public function testUserHashUserWithAuthorizationHeader($arg, $options)
188+
{
189+
$userContextSubscriber = new UserContextSubscriber($arg);
190+
191+
$request = Request::create('/foo', 'GET', array(), array(), array(), array('HTTP_AUTHORIZATION' => 'foo'));
192+
193+
// Add a cookie which should not be available in the eventual hash request anymore
194+
$request->cookies->set('foo', 'bar');
195+
196+
$hashRequest = Request::create($options['user_hash_uri'], $options['user_hash_method'], array(), array(), array(), $request->server->all());
197+
$hashRequest->attributes->set('internalRequest', true);
198+
$hashRequest->headers->set('Accept', $options['user_hash_accept_header']);
199+
200+
// Ensure request properties have been filled up.
201+
$hashRequest->getPathInfo();
202+
$hashRequest->getMethod();
203+
204+
$expectedContextHash = 'my_generated_hash';
205+
$hashResponse = new Response();
206+
$hashResponse->headers->set($options['user_hash_header'], $expectedContextHash );
207+
208+
$that = $this;
209+
$this->kernel
210+
->expects($this->once())
211+
->method('handle')
212+
->with(
213+
$this->callback(function (Request $request) use ($that, $hashRequest) {
214+
// we need to call some methods to get the internal fields initialized
215+
$request->getMethod();
216+
$request->getPathInfo();
217+
$that->assertEquals($hashRequest, $request);
218+
$that->assertCount(0, $request->cookies->all());
219+
220+
return true;
221+
})
222+
)
223+
->will($this->returnValue($hashResponse));
224+
225+
$event = new CacheEvent($this->kernel, $request);
226+
227+
$userContextSubscriber->preHandle($event);
228+
$response = $event->getResponse();
229+
230+
$this->assertNull($response);
231+
$this->assertTrue($request->headers->has($options['user_hash_header']));
232+
$this->assertSame($expectedContextHash, $request->headers->get($options['user_hash_header']));
233+
}
180234

181235
/**
182236
* @expectedException \InvalidArgumentException

0 commit comments

Comments
 (0)