简体   繁体   English

[Symfony 5]注销后的确认信息

[英][Symfony 5]Confirmation message after logout

On Symfony 5, using the built-in login system, it seems impossible to add a confirmation message after logout. On Symfony 5、使用内置登录系统,注销后好像无法添加确认信息。 I have followed strictly the steps described on the official website .我严格按照官方网站上描述的步骤进行操作。 Unfortunately, the method logout inside the SecurityController is useless.不幸的是,SecurityController 中的注销方法没有用。 I'm redirected directly on the login page.我直接在登录页面上重定向。

Here you will have my security.yaml file:在这里你会有我的 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] }

And the Controller:和 Controller:

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

?>

Thank you for your help !感谢您的帮助 !

For anyone who's wondering how exactly they can implement the external redirect with the new logout customization:对于想知道如何使用新的注销自定义来实现外部重定向的任何人:

As stated in the documentation , create a new CustomLogoutListener class and add it to your services.yml configuration.文档中所述,创建一个新的 CustomLogoutListener 类并将其添加到您的 services.yml 配置中。

The CustomLogoutListener class should implement the onSymfonyComponentSecurityHttpEventLogoutEvent method, which will receive the LogoutEvent as a parameter, that will allow you to set the response: 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

logout method in SecurityController won't actually get hit because Symfony will intercept the request. SecurityController 中的 logout 方法实际上不会被命中,因为 Symfony 会拦截请求。 if you need to do something after logout you can use logout success handler如果您在注销后需要做一些事情,您可以使用注销成功处理程序

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

and you can register your logout success handler to security.yaml您可以将注销成功处理程序注册到 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

Thanks to Indra Gunawan, this solution works.感谢 Indra Gunawan,这个解决方案有效。 My goal was to redirect to the login page with a message like "You've been successfully logged out".我的目标是重定向到登录页面,并显示“您已成功注销”之类的消息。

In that case, the LogoutSuccessHandler must be adapted to route to the login page :在这种情况下,必须调整 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']));
    }
}

The route login need to be defined in routes.yaml :路由登录需要在 routes.yaml 中定义:

login:
    path: /login
    controller: App\Controller\SecurityController::login

logout:
    path: /logout
    methods: GET

In that case, when logout, you will be redirected on an url like : /login?logout=success在这种情况下,当注销时,您将被重定向到一个 url,如:/login?logout=success

Lastely, you can catch logout parameter in twig template like :最后,您可以在 twig 模板中捕获注销参数,例如:

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

As of version 5.1 LogoutSuccessHandlerInterface is deprecated, it is recommended to use LogoutEvent .从 5.1 版本开始,不推荐使用LogoutSuccessHandlerInterface ,建议使用LogoutEvent

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

But there are no examples or information about LogoutEvent in the official documentation但是官方文档中没有关于LogoutEvent的例子或信息

Here is the doc for the LogoutEvent :这是 LogoutEvent 的文档:

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

You must create an event and implement the onSymfonyComponentSecurityHttpEventLogoutEvent's method.您必须创建一个事件并实现 onSymfonyComponentSecurityHttpEventLogoutEvent 的方法。 Its work for me它为我工作

If you are using Symfony 6 and above you can use as bellow如果您使用的是 Symfony 6 及更高版本,您可以使用如下方式

<?php

namespace App\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Http\Event\LogoutEvent;

class LogoutListener implements EventSubscriberInterface
{

    public function onLogout(LogoutEvent $logoutEvent): void
    {
        // Do your stuff
    }

    public static function getSubscribedEvents(): array
    {
        return [
            LogoutEvent::class => 'onLogout',
        ];
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM