【问题标题】:[Symfony 5]Confirmation message after logout[Symfony 5]注销后的确认信息
【发布时间】:2020-07-14 20:23:57
【问题描述】:

在 Symfony 5 上,使用内置的登录系统,注销后似乎无法添加确认消息。我严格按照the official website 中描述的步骤进行操作。不幸的是,SecurityController 内部的方法 logout 是没有用的。我直接在登录页面被重定向。

在这里您将获得我的 security.yaml 文件:

security:
encoders:
    App\Entity\User:
        algorithm: auto


# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
    # used to reload user from session & other features (e.g. switch_user)
    app_user_provider:
        entity:
            class: App\Entity\User
            property: email
    # used to reload user from session & other features (e.g. switch_user)
firewalls:
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false
    main:
        anonymous: lazy
        provider: app_user_provider
        guard:
            authenticators:
                - App\Security\LoginFormAuthenticator
        logout:
            path: logout
            target: login

        remember_me:
            secret:   '%kernel.secret%'
            lifetime: 604800 # 1 week in seconds
            path:     home
            always_remember_me: true

        # activate different ways to authenticate
        # https://symfony.com/doc/current/security.html#firewalls-authentication

        # https://symfony.com/doc/current/security/impersonating_user.html
        # switch_user: true

# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
    - { path: ^/logout$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/, roles: IS_AUTHENTICATED_FULLY }
    - { path: ^/admin, roles: [IS_AUTHENTICATED_FULLY, ROLE_ADMIN] }
    - { path: ^/profile, roles: [IS_AUTHENTICATED_FULLY, ROLE_USER] }

还有控制器:

<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;

class SecurityController extends AbstractController
{
    public function login(AuthenticationUtils $authenticationUtils): Response
    {
        if ($this->getUser()) {
            return $this->redirectToRoute('home');
        }

        // get the login error if there is one
        $error = $authenticationUtils->getLastAuthenticationError();

        return $this->render('security/login.html.twig', ['last_username' => null, 'error' => $error]);
    }

    public function logout()
    {
        throw new \Exception('Don\'t forget to activate logout in security.yaml');
    }
}

?>

感谢您的帮助!

【问题讨论】:

    标签: symfony security logout


    【解决方案1】:

    对于想知道如何通过新的注销自定义实现外部重定向的任何人:

    documentation 中所述,创建一个新的 CustomLogoutListener 类并将其添加到您的 services.yml 配置中。

    CustomLogoutListener 类应该实现 onSymfonyComponentSecurityHttpEventLogoutEvent 方法,该方法将接收 LogoutEvent 作为参数,这将允许您设置响应:

    namespace App\EventListener;
    
    use JetBrains\PhpStorm\NoReturn;
    use Symfony\Component\HttpFoundation\RedirectResponse;
    use Symfony\Component\HttpFoundation\Response;
    use Symfony\Component\Security\Http\Event\LogoutEvent;
    
    class CustomLogoutListener
    {
        /**
         * @param LogoutEvent $logoutEvent
         * @return void
         */
        #[NoReturn]
        public function onSymfonyComponentSecurityHttpEventLogoutEvent(LogoutEvent $logoutEvent): void
        {
            $logoutEvent->setResponse(new RedirectResponse('https://where-you-want-to-redirect.com', Response::HTTP_MOVED_PERMANENTLY));
        }
    }
    
    
    # config/services.yaml
    services:
        # ...
        App\EventListener\CustomLogoutListener:
            tags:
                - name: 'kernel.event_listener'
                  event: 'Symfony\Component\Security\Http\Event\LogoutEvent'
                  dispatcher: security.event_dispatcher.main
    

    【讨论】:

    • 为了避免这个长方法名称onSymfonyComponentSecurityHttpEventLogoutEvent:在你的services.yaml中设置method: onLogoutEvent-Tag,这样你就可以将你的方法命名为onLogoutEvent
    【解决方案2】:

    这是 LogoutEvent 的文档:

    https://symfony.com/blog/new-in-symfony-5-1-simpler-logout-customization

    您必须创建一个事件并实现 onSymfonyComponentSecurityHttpEventLogoutEvent 的方法。 它对我有用

    【讨论】:

    • 为了避免这个长方法名onSymfonyComponentSecurityHttpEventLogoutEvent:在你的services.yaml中设置method: onLogoutEvent-Tag,这样你就可以将你的方法命名为onLogoutEvent
    【解决方案3】:

    从 5.1 版本开始,LogoutSuccessHandlerInterface 已弃用,建议使用 LogoutEvent

    Symfony\Component\Security\Http\Logout\LogoutSuccessHandlerInterface 已弃用

    但官方文档中没有关于LogoutEvent的示例或信息

    【讨论】:

      【解决方案4】:

      感谢 Indra Gunawan,此解决方案有效。我的目标是重定向到登录页面,并显示“您已成功注销”之类的消息。

      在这种情况下,必须调整 LogoutSuccessHandler 以路由到登录页面:

      namespace App\Logout;
      
      use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
      use Symfony\Component\HttpFoundation\Request;
      use Symfony\Component\Security\Http\Logout\LogoutSuccessHandlerInterface;
      use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
      use Symfony\Component\HttpFoundation\RedirectResponse;
      
      class MyLogoutSuccessHandler extends AbstractController implements LogoutSuccessHandlerInterface
      {
      
          private $urlGenerator;
      
          public function __construct(UrlGeneratorInterface $urlGenerator)
          {
              $this->urlGenerator = $urlGenerator;
          }
      
          public function onLogoutSuccess(Request $request)
          {
              return new RedirectResponse($this->urlGenerator->generate('login', ['logout' => 'success']));
          }
      }
      

      路由登录需要在 routes.yaml 中定义:

      login:
          path: /login
          controller: App\Controller\SecurityController::login
      
      logout:
          path: /logout
          methods: GET
      

      在这种情况下,当您注销时,您将被重定向到如下网址:/login?logout=success

      最后,您可以在 twig 模板中捕获注销参数,例如:

          {%- if app.request('logout') -%}
              <div class="alert alert-success">{% trans %}Logout successful{% endtrans %}</div>
          {%- endif -%}   
      

      【讨论】:

        【解决方案5】:

        SecurityController 中的 logout 方法实际上不会被命中,因为 Symfony 会拦截请求。 如果您需要在注销后执行某些操作,您可以使用注销成功处理程序

        namespace App\Logout;
        
        use Symfony\Component\HttpFoundation\Request;
        use Symfony\Component\HttpFoundation\Response;
        use Symfony\Component\Security\Http\Logout\LogoutSuccessHandlerInterface;
        
        class MyLogoutSuccessHandler implements LogoutSuccessHandlerInterface
        {
            /**
             * {@inheritdoc}
             */
            public function onLogoutSuccess(Request $request)
            {
                // you can do anything here
                return new Response('logout successfully'); // or render a twig template here, it's up to you
            }
        }
        

        您可以将注销成功处理程序注册到 security.yaml

        firewalls:
            main:
                anonymous: lazy
                provider: app_user_provider
                guard:
                    authenticators:
                        - App\Security\LoginFormAuthenticator
                logout:
                    path: logout
                    success_handler: App\Logout\MyLogoutSuccessHandler # assume you have enable autoconfigure for servicess or you need to register the handler
        

        【讨论】:

          猜你喜欢
          • 2022-08-08
          • 2017-04-25
          • 2012-10-09
          • 2020-03-02
          • 1970-01-01
          • 2021-04-22
          • 2013-09-18
          • 1970-01-01
          • 2015-07-11
          相关资源
          最近更新 更多