Symfony3 Сохраняет языковой стандарт после входа в систему


Проблема, с которой я сталкиваюсь, заключается в том, что пользователь меняет язык на странице входа - это работает, но после входа пользователя - он снова возвращается к умолчанию. Как сделать так, чтобы пользователь, выбранный перед входом в систему, сохранял тот же язык, чтобы оставаться после входа в систему? Я пытался найти это в stackoverflow, но не смог найти никакого рабочего результата.

Безопасность.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

Маршрутизация.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                

Язык изменен:

<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>

Любые идеи или примеры будут оценены по достоинству!

Author: JustinasT, 2017-01-16

1 answers

По умолчанию компонент безопасности сохраняет информацию URI последнего запроса (например, /en/admin) в переменной сеанса с именем _security.main.target_path (при этом main является именем брандмауэра, определенным в security.yml). После успешного входа в систему пользователь перенаправляется на этот путь, чтобы помочь ему продолжить с последней известной страницы, которую он посетил.

Примечание: Независимо от того, сколько раз менялся язык на странице входа в систему, потому что брандмауэр всегда перенаправляет на /en/admin/ после успешного входа в систему, поэтому локаль снова меняется на en.

Чтобы исправить это, вам может потребоваться изменить поведение целевого пути по умолчанию:

Класс Прослушивателя исключений:

// 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') 
            );
        }
    }
}

Это создаст старый маршрут после входа в систему с текущей локализацией.

Конфигурация:

Для Symfony 2:

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

Для Symfony 3:

Возможно, вам потребуется создать проход компилятора и изменить этот класс вручную:

// 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');
    }
}

Наконец-то зарегистрируйте пропуск компилятора в своем пакете:

// src/AppBundle/AppBundle.php

class AppBundle extends Bundle
{   
    public function build(ContainerBuilder $container)
    {
        $container->addCompilerPass(new ExceptionListenerPass());
    }
}
 3
Author: yceruto, 2017-01-19 03:43:57