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



在Symfony 5上,使用内置的登录系统,似乎不可能在注销后添加确认消息。我严格遵守了官方网站上描述的步骤。不幸的是,SecurityController中的方法logout是无用的。我直接在登录页面上重定向。

给你我的安全文件:

security:
encoders:
AppEntityUser:
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: AppEntityUser
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:
- AppSecurityLoginFormAuthenticator
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 AppController;
use SymfonyBundleFrameworkBundleControllerAbstractController;
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentSecurityHttpAuthenticationAuthenticationUtils;
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');
}
}
?>

谢谢你的帮助!

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

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

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

namespace AppEventListener;
use JetBrainsPhpStormNoReturn;
use SymfonyComponentHttpFoundationRedirectResponse;
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentSecurityHttpEventLogoutEvent;
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:
# ...
AppEventListenerCustomLogoutListener:
tags:
- name: 'kernel.event_listener'
event: 'SymfonyComponentSecurityHttpEventLogoutEvent'
dispatcher: security.event_dispatcher.main
SecurityController中的

logout方法实际上不会被命中,因为Symfony会拦截请求。如果您需要在注销后做一些事情,您可以使用注销成功处理程序

namespace AppLogout;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentSecurityHttpLogoutLogoutSuccessHandlerInterface;
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:
- AppSecurityLoginFormAuthenticator
logout:
path: logout
success_handler: AppLogoutMyLogoutSuccessHandler # assume you have enable autoconfigure for servicess or you need to register the handler

由于版本5.1的LogoutSuccessHandlerInterface已弃用,建议使用LogoutEvent

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

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

多亏了Indra Gunawan,这个解决方案才得以运行。我的目标是重定向到登录页面,并显示一条类似"您已成功注销"的消息。

在这种情况下,LogoutSuccessHandler必须适用于路由到登录页面:

namespace AppLogout;
use SymfonyBundleFrameworkBundleControllerAbstractController;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentSecurityHttpLogoutLogoutSuccessHandlerInterface;
use SymfonyComponentRoutingGeneratorUrlGeneratorInterface;
use SymfonyComponentHttpFoundationRedirectResponse;
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: AppControllerSecurityController::login
logout:
path: /logout
methods: GET

在这种情况下,当注销时,您将被重定向到一个url上,如:/login?logout=成功

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

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

这是LogoutEvent的文档:

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

您必须创建一个事件并实现onSymfonyComponentSecurityHttpEventLogoutEvent的方法。它对我来说很好

如果您使用的是Symfony 6及以上版本,则可以使用以下

<?php
namespace AppEventSubscriber;
use SymfonyComponentEventDispatcherEventSubscriberInterface;
use SymfonyComponentSecurityHttpEventLogoutEvent;
class LogoutListener implements EventSubscriberInterface
{
public function onLogout(LogoutEvent $logoutEvent): void
{
// Do your stuff
}
public static function getSubscribedEvents(): array
{
return [
LogoutEvent::class => 'onLogout',
];
}
}

相关内容

  • 没有找到相关文章

最新更新