Commit 9b5c52be authored by Benni Mack's avatar Benni Mack
Browse files

[!!!][TASK] Set no-cache headers only to PSR-7 Response

The related HTTP no-cache headers (e.g. when a user is logged in)
are now only set via PSR-15 middlewares (already in place for
Backend Users, but now added for Frontend Users / Sessions as well),
but not directly emitted via "header()" functions anymore.

The next steps for having autonomous tests are:
* Do not send cookies directly anymore
* Double-check backend login cookies and
* Check for ImmediateResponse / HttpUtility::redirect() methods
* Evaluate the HTTP headers emitted inside the Installer.

Resolves: #92997
Releases: master
Change-Id: I7f1e9826b3d61977cb24e4622e0888e301b807e3
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/67001


Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: Georg Ringer's avatarGeorg Ringer <georg.ringer@gmail.com>
Tested-by: Markus Klein's avatarMarkus Klein <markus.klein@typo3.org>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Georg Ringer's avatarGeorg Ringer <georg.ringer@gmail.com>
Reviewed-by: Markus Klein's avatarMarkus Klein <markus.klein@typo3.org>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
parent 8cec795a
......@@ -326,8 +326,6 @@ abstract class AbstractUserAuthentication implements LoggerAwareInterface
$this->newSessionID = true;
}
// Set all possible headers that could ensure that the script is not cached on the client-side
$this->sendHttpHeaders();
// Load user session, check to see if anyone has submitted login-information and if so authenticate
// the user with the session. $this->user[uid] may be used to write log...
$this->checkAuthentication();
......@@ -348,40 +346,6 @@ abstract class AbstractUserAuthentication implements LoggerAwareInterface
}
}
/**
* Set all possible headers that could ensure that the script
* is not cached on the client-side.
*
* Only do this if $this->sendNoCacheHeaders is set.
*/
protected function sendHttpHeaders()
{
// skip sending the "no-cache" headers if it's a CLI request or the no-cache headers should not be sent.
if (!$this->sendNoCacheHeaders || Environment::isCli()) {
return;
}
$httpHeaders = $this->getHttpHeaders();
foreach ($httpHeaders as $httpHeaderName => $value) {
header($httpHeaderName . ': ' . $value);
}
}
/**
* Get the http headers to be sent if an authenticated user is available, in order to disallow
* browsers to store the response on the client side.
*
* @return array
*/
protected function getHttpHeaders(): array
{
return [
'Expires' => 0,
'Last-Modified' => gmdate('D, d M Y H:i:s') . ' GMT',
'Cache-Control' => 'no-cache, must-revalidate',
'Pragma' => 'no-cache'
];
}
/**
* Sets the session cookie for the current disposal.
*
......
.. include:: ../../Includes.txt
===================================================================================================
Breaking: #92997 - Authentication-related HTTP cache headers are emitted only by PSR-15 middlewares
===================================================================================================
See :issue:`92997`
Description
===========
In previous TYPO3 versions, when a user session was initiated or set
(e.g. due to login or cookie), :php:`AbstractUserAuthentication` was instructed
to send HTTP headers immediately via the PHP function :php:`header()`.
These headers were sent directly to the client without having a chance to
manipulate a response, or simulate this behavior via proper tests in a testing
suite.
These HTTP headers for not caching a HTTP response were already attached to the
PSR-7 Response when an active Backend user was available in Frontend and Backend
requests, but not when a Frontend user was logged in.
The internal methods in :php:`AbstractUserAuthentication` are removed.
Impact
======
These headers are now only sent via the PSR-7 Response object, and emitted at
the very end of a Request/Response lifecycle in a TYPO3 Application (for Frontend
and Backend Requests), and not via the :php:`header()` function anymore.
Affected Installations
======================
TYPO3 installations with custom extensions manipulating HTTP headers or the
options within `AbstractUserAuthentication` to send such headers.
Migration
=========
If any changes regarding the PSR-7 Response headers are needed, it is
recommended to build a custom PSR-15 middleware in a TYPO3 Extension.
.. index:: Backend, Frontend, PHP-API, FullyScanned, ext:core
......@@ -72,17 +72,4 @@ class AbstractUserAuthenticationTest extends UnitTestCase
$result = $mock->getAuthInfoArray();
self::assertEquals('', $result['db_user']['checkPidList']);
}
/**
* @test
*/
public function getHttpHeadersReturnsNoCacheHeaders()
{
$_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Windows NT 6.2; rv:22.0) Gecko/20130405 Firefox/23.0';
$_SERVER['HTTPS'] = 'on';
$subject = $this->getAccessibleMockForAbstractClass(AbstractUserAuthentication::class, [], '', false);
$subject->_set('loginType', 'BE');
$result = $subject->_call('getHttpHeaders');
self::assertEquals($result['Pragma'], 'no-cache');
}
}
......@@ -81,6 +81,9 @@ class FrontendUserAuthenticator implements MiddlewareInterface
// Store session data for fe_users if it still exists
if ($frontendUser instanceof FrontendUserAuthentication) {
$frontendUser->storeSessionData();
if ($frontendUser->sendNoCacheHeaders) {
$response = $this->applyHeadersToResponse($response);
}
}
return $response;
......@@ -122,4 +125,27 @@ class FrontendUserAuthenticator implements MiddlewareInterface
}
return $request;
}
/**
* Adding headers to the response to avoid caching on the client side.
* These headers will override any previous headers of these names sent.
* Get the http headers to be sent if an authenticated user is available,
* in order to disallow browsers to store the response on the client side.
*
* @param ResponseInterface $response
* @return ResponseInterface the modified response object.
*/
protected function applyHeadersToResponse(ResponseInterface $response): ResponseInterface
{
$headers = [
'Expires' => 0,
'Last-Modified' => gmdate('D, d M Y H:i:s') . ' GMT',
'Cache-Control' => 'no-cache, must-revalidate',
'Pragma' => 'no-cache'
];
foreach ($headers as $headerName => $headerValue) {
$response = $response->withHeader($headerName, (string)$headerValue);
}
return $response;
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment