Symfony5配置多提供者多防火墙后无法正常登出问题求助
问题根因
你当前的两个防火墙customer和administrator的路径匹配规则均未覆盖/logout路径,因此访问/logout时没有匹配到任何配置了登出规则的防火墙,Symfony的登出监听器不会触发,才会直接执行控制器内的代码抛出异常。你将某防火墙重命名为main后,main作为Symfony默认的兜底防火墙,会承接所有未匹配到前面规则的请求,因此/logout请求会被对应防火墙的登出监听器拦截,功能正常。
解决方案1:调整防火墙匹配规则(推荐,无需修改代码)
只需要把/logout路径加入两个防火墙的匹配规则即可:
firewalls: dev: pattern: ^/(_(profiler|wdt)|css|images|js)/ security: false customer: # 新增/logout到匹配规则 pattern: ^/profile|/login|/logout entry_point: App\Security\CustomerAuthenticator provider: app_customer_provider custom_authenticator: App\Security\CustomerAuthenticator logout: path: app_logout target: / invalidate_session: true administrator: # 新增/logout到匹配规则 pattern: ^/admin|/accessadmin|/logout entry_point: App\Security\AdminAuthenticator lazy: true provider: app_admin_provider custom_authenticator: App\Security\AdminAuthenticator logout: path: app_logout target: / invalidate_session: true
调整后/logout请求会匹配到用户当前登录身份对应的防火墙,自动触发登出逻辑,不需要修改控制器代码。
解决方案2:在控制器中手动实现登出逻辑
如果你确实需要在控制器方法中自行处理登出,可以按以下方式编写代码:
use Symfony\Component\Security\Http\Event\LogoutEvent; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\Request; /** * @Route("/logout", name="app_logout") */ public function logout(Request $request, EventDispatcherInterface $eventDispatcher) { // 触发Symfony原生登出事件,自动执行销毁会话、清除令牌等原生登出操作 $token = $this->get('security.token_storage')->getToken(); if ($token) { $logoutEvent = new LogoutEvent($request, $token); $eventDispatcher->dispatch($logoutEvent); // 清空令牌存储 $this->get('security.token_storage')->setToken(null); // 销毁会话 $request->getSession()->invalidate(); } // 跳转到首页 return $this->redirectToRoute('home'); }
注意这种方式需要你自行处理不同身份用户登出后的跳转逻辑,不如直接调整防火墙配置的方式简洁。
内容的提问来源于stack exchange,提问作者lerdouille
相关产品推荐
相关产品推荐

