In order to create a restricted area on a website, I set up User Context Caching following this guide. https://docs.sulu.io/en/2.5/cookbook/user-context-caching.html
The login, logout works, but when multiple users access the website, the user context suddenly changes. E.g. I log on with user A, after some clicks I am suddenly user B.
The username is displayed in the page header template with {{ app.user.username }}
).
In live environment the page is hosted using nginx (for static content) and apache (for dynamic content). Do I need some special configuration there?
Here are the configuration files.
config/routes/fos_http_cache.yaml
user_context_hash:
path: /_fos_user_context_hash
config/packages/fos_http_cache.yaml
fos_http_cache:
proxy_client:
symfony:
use_kernel_dispatcher: true
user_context:
enabled: true
role_provider: true
hash_cache_ttl: 0
src/Kernel.php
<?php
declare(strict_types=1);
namespace App;
/*
* This file is part of Sulu.
*
* (c) Sulu GmbH
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
use FOS\HttpCache\SymfonyCache\HttpCacheProvider;
use Sulu\Bundle\HttpCacheBundle\Cache\SuluHttpCache;
use Sulu\Component\HttpKernel\SuluKernel;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\HttpKernelInterface;
class Kernel extends SuluKernel implements HttpCacheProvider
{
private ?HttpKernelInterface $httpCache = null;
protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void
{
$container->setParameter('container.dumper.inline_class_loader', true);
parent::configureContainer($container, $loader);
}
public function getHttpCache(): HttpKernelInterface
{
if (!$this->httpCache instanceof HttpKernelInterface) {
$this->httpCache = new SuluHttpCache($this);
// Activate the following for user based caching see also:
// https://foshttpcachebundle.readthedocs.io/en/latest/features/user-context.html
$this->httpCache->addSubscriber(
new \FOS\HttpCache\SymfonyCache\UserContextListener([
'session_name_prefix' => 'SULUSESSID',
])
);
}
return $this->httpCache;
}
}
config/webspaces/webspace.xml
<?xml version="1.0" encoding="utf-8"?>
<webspace xmlns="http://schemas.sulu.io/webspace/webspace"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schemas.sulu.io/webspace/webspace http://schemas.sulu.io/webspace/webspace-1.1.xsd">
<!-- See: http://docs.sulu.io/en/latest/book/webspaces.html how to configure your webspace-->
<name>example.io</name>
<key>example</key>
<localizations>
<!-- See: http://docs.sulu.io/en/latest/book/localization.html how to add new localizations -->
<localization language="en" default="true" />
<localization language="es" />
</localizations>
<security permission-check="true">
<system>private_sale</system>
</security>
<default-templates>
<default-template type="page">default</default-template>
<default-template type="home">homepage</default-template>
</default-templates>
<templates>
<template type="search">search/search</template>
<!-- See: http://docs.sulu.io/en/latest/cookbook/custom-error-page.html how to create a custom error page -->
<template type="error">error/error</template>
<template type="error-404">error/error-404</template>
</templates>
<navigation>
<contexts>
<context key="main">
<meta>
<title lang="en">Main Navigation</title>
<title lang="de">Hauptnavigation</title>
</meta>
</context>
<context key="footer_quicklinks">
<meta>
<title lang="en">Footer Quicklinks</title>
<title lang="en">Footer Quicklinks</title>
</meta>
</context>
<context key="footer_support">
<meta>
<title lang="en">Footer Support</title>
<title lang="en">Footer Support</title>
</meta>
</context>
</contexts>
</navigation>
<portals>
<portal>
<name>example.io</name>
<key>example</key>
<environments>
<environment type="prod">
<urls>
<url>{host}/{localization}</url>
</urls>
</environment>
<environment type="stage">
<urls>
<url>{host}/{localization}</url>
</urls>
</environment>
<environment type="test">
<urls>
<url>{host}/{localization}</url>
</urls>
</environment>
<environment type="dev">
<urls>
<url>{host}/{localization}</url>
</urls>
</environment>
</environments>
</portal>
</portals>
</webspace>
You did misunderstand user context based caching. Pages in Sulu are cached, and the cache response is returned for every user having the same cache hash. The cache hash, in this scenario, is normally configured based on the roles a user has.
So User A visit "Page X", that page gets cached, and if you render its username that username is also cached.
User B visits "Page X", and get the same page returned, but as you rendered the username, you will see the username of the authenticated user that previously visited the page.
All things which are user specific never ever should be directly rendered on pages itself.
Something which is specific for a single user should be AJAX loaded, in this case the Username. You can also use ESI, but ESI doesn't make sense in case of something for a single specific user as it blocks the response time and would make it slow.
Symfony already ships a render_hinclude
where you can call a custom controller which allows you fast implement such things:https://symfony.com/doc/current/templates.html#templates-hinclude