Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony3 Keeping locale after login

Problem I have, is when user changes language in login page - it works, but after user login - it is back to default again. How to make it possible to the keep same language user selected before login, to stay after login? I've tried looking this up on stackoverflow, but wasn't able to find any working result.

security.yml:

security:

    encoders:
        AppBundle\Entity\User:
            algorithm: bcrypt

    role_hierarchy:
        ROLE_ADMIN: ROLE_PREMIUM
        ROLE_PREMIUM: ROLE_USER

    providers:
        our_db_provider:
            entity:
                class: AppBundle:User
                property: email

        in_memory:
            memory: ~

    firewalls:
        # disables authentication for assets and the profiler, adapt it according to your needs
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false

        main:
            anonymous: ~

            form_login:
                #galima nurodyti kur nukreipia loginas
                login_path: login
                check_path: login
                csrf_token_generator: security.csrf.token_manager 
            logout:
                path:   /logout

            pattern:    ^/
            http_basic: ~
            provider: our_db_provider
            access_denied_url: homepage

routing.yml

app:
    resource: "@AppBundle/Controller/"
    type:     annotation
    prefix:   /{_locale}
    requirements:
        _locale: lt|en|ru

root:
    path: /
    defaults:
        _controller: FrameworkBundle:Redirect:urlRedirect
        path: /%locale%/
        permanent: true  

login:
    path:  /{_locale}/login
    defaults: { _controller: AppBundle:Security:login }
    requirements:
        _method:  GET
        _locale: lt|en|ru

logout:
    path: /logout
    defaults:
        _controller: FrameworkBundle:Redirect:urlRedirect
        path: /{_locale}/login
        permanent: true        

register:
    path:  /{_locale}/register
    defaults: { _controller: AppBundle:Registration:register }
    requirements:
        _method:  GET
        _locale: lt|en|ru                

Language changed by:

<ul class="top-menu-list top-menu-languages">
    <li><a href="{{ path(app.request.attributes.get('_route'), app.request.query.all|merge({'_locale': 'lt'})) }}">LT</a></li>
    <li><a href="{{ path(app.request.attributes.get('_route'), app.request.query.all|merge({'_locale': 'en'})) }}">EN</a></li>
    <li><a href="{{ path(app.request.attributes.get('_route'), app.request.query.all|merge({'_locale': 'ru'})) }}">RU</a></li>
</ul>

Any ideas or examples would be appreciated!

like image 513
JustinasT Avatar asked Oct 29 '22 13:10

JustinasT


1 Answers

By default, the Security component retains the information of the last request URI (e.g. /en/admin) in a session variable named _security.main.target_path (with main being the name of the firewall, defined in security.yml). Upon a successful login, the user is redirected to this path, as to help them continue from the last known page they visited.

Note: No matter how many times the language is changed on the login page, because the firewall always redirect to /en/admin/ after success login, so the locale changes again to en.

To fix that you might need to change the default Target Path Behavior:

The Exception Listener Class:

// src/AppBundle/Security/Firewall/ExceptionListener.php

use Symfony\Component\Security\Http\Firewall\ExceptionListener as BaseExceptionListener;

class ExceptionListener extends BaseExceptionListener
{
    use TargetPathTrait;

    protected function setTargetPath(Request $request)
    {
        if ($request->hasSession() && $request->isMethodSafe(false) && !$request->isXmlHttpRequest()) {
            $this->saveTargetPath(
                $request->getSession(), 
                // the firewall name 
                'admin', 
                // save the route name instead of the URI
                $request->attributes->get('_route') 
            );
        }
    }
}

This generate the old route after login with the current locale.

Configuration:

For Symfony 2:

# app/config/services.yml
parameters:
    # ...
    security.exception_listener.class: AppBundle\Security\Firewall\ExceptionListener

For Symfony 3:

You might need create a compiler pass and change this class manually:

// src/AppBundle/DependencyInjection/Compiler/ExceptionListenerPass.php;

class ExceptionListenerPass implements CompilerPassInterface
{
    /**
     * {@inheritdoc}
     */
    public function process(ContainerBuilder $container)
    {
        $definition = $container->getDefinition('security.exception_listener.admin');
        $definition->setClass('AppBundle\Security\Firewall\ExceptionListener');
    }
}

Finally register the compiler pass in your bundle:

// src/AppBundle/AppBundle.php

class AppBundle extends Bundle
{   
    public function build(ContainerBuilder $container)
    {
        $container->addCompilerPass(new ExceptionListenerPass());
    }
}
like image 98
yceruto Avatar answered Nov 15 '22 18:11

yceruto