I'm using the basic user login/logout system provided with Symfony and it works fine as long as people log in. In that case the $user object is always provided as needed.
The problem is then when logged out (or not lgged in yet) there is no user object. Is there a possibility to have (in that case) a default user object provided with my own default values?
Thanks for your suggestions
Because the solution mention above by @Chopchop (thanks anyway for your effort) didn't work here I wrote a little workaround.
I created a new class called myController which extends Controller. The only function i override is the getUser() function. There I implement it like this:
public function getUser()
{
$user = Controller::getUser();
if ( !is_object($user) )
{
$user = new \ACME\myBundle\Entity\User();
$user->setUserLASTNAME ('RaRa');
$user->setID (0);
// etc...
}
return $user;
}
This works fine for me now. The only problem is that you really have to be careful NOT to forget to replace Controller by myController in all your *Controller.php files. So, better suggestions still welcome.
Works in Symfony 3.3
Using the suggestion of @Sfblaauw, I came up with a solution that uses a CompilerPass
.
AppBundle/AppBundle.php
class AppBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new OverrideAnonymousUserCompilerPass());
}
}
OverrideAnonymousUserCompilerPass.php
class OverrideAnonymousCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$definition = $container->getDefinition('security.authentication.listener.anonymous');
$definition->setClass(AnonymousAuthenticationListener::class);
}
}
AnonymousAuthenticationListener.php
class AnonymousAuthenticationListener implements ListenerInterface
{
private $tokenStorage;
private $secret;
private $authenticationManager;
private $logger;
public function __construct(TokenStorageInterface $tokenStorage, $secret, LoggerInterface $logger = null, AuthenticationManagerInterface $authenticationManager = null)
{
$this->tokenStorage = $tokenStorage;
$this->secret = $secret;
$this->authenticationManager = $authenticationManager;
$this->logger = $logger;
}
public function handle(GetResponseEvent $event)
{
if (null !== $this->tokenStorage->getToken()) {
return;
}
try {
// This is the important line:
$token = new AnonymousToken($this->secret, new AnonymousUser(), array());
if (null !== $this->authenticationManager) {
$token = $this->authenticationManager->authenticate($token);
}
$this->tokenStorage->setToken($token);
if (null !== $this->logger) {
$this->logger->info('Populated the TokenStorage with an anonymous Token.');
}
} catch (AuthenticationException $failed) {
if (null !== $this->logger) {
$this->logger->info('Anonymous authentication failed.', array('exception' => $failed));
}
}
}
}
This file is a copy of the AnonymousAuthenticationListener that comes with Symfony, but with the AnonymousToken
constructor changed to pass in an AnonymousUser
class instead of a string. In my case, AnonymousUser
is a class that extends my User
object, but you can implement it however you like.
These changes mean that {{ app.user }}
in Twig and UserInterface
injections in PHP will always return a User
: you can use isinstance
to tell if it's an AnonymousUser
, or add a method isLoggedIn
to your User
class which returns true
in User
but false
in AnonymousUser
.
you can redirect the user not authenticated and force a fake login (to create a user ANONYMOUS)
and set it as well on logout
public function logoutAction(){
$em = $this->getDoctrine()->getManager();
$user = $em->getRepository('VendorBundle:User')->findByUserName('annonymous');
$session = $this->getRequest()->getSession();
$session->set('user', $user);
}
and if user is not set
public function checkLoginAction(){
if(!$session->get('user')){
$em = $this->getDoctrine()->getManager();
$user = $em->getRepository('VendorBundle:User')->findByUserName('annonymous');
$session = $this->getRequest()->getSession();
$session->set('user', $user);
}
//this->redirect('/');
}
in you security.yml
security:
firewalls:
main:
access_denied_url: /check_login/
access_control:
- { path: ^/$, role: ROLE_USER }
This is only an example i haven't tested (and will probably don't, since i don't get the purpose of doing this:) )
Using Symfony 2.6
Like Gordon says use the authentication listener to override the default anonymous user. Now you can add the properties that you need to the anonymous user, in my case the language and the currency.
security.yml
parameters:
security.authentication.listener.anonymous.class: AppBundle\Security\Http\Firewall\AnonymousAuthenticationListener
AnonymousAuthenticationListener.php
namespace AppBundle\Security\Http\Firewall;
...
use AppBundle\Security\User\AnonymousUser;
class AnonymousAuthenticationListener implements ListenerInterface
{
...
public function handle(GetResponseEvent $event)
{
...
try {
$token = new AnonymousToken($this->key, new AnonymousUser(), array());
...
}
}
}
AnonymousUser.php
class AnonymousUser implements UserInterface
{
public function getUsername() { return 'anon.'; }
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.