[英]avoid browser back button after symfony logout
我在一个 symfony 项目中工作。 它几乎准备好了,身份验证流程很好......但是在用户注销后,他可以通过按浏览器中的后退按钮返回系统。
用户无法使用系统,如果他点击某个链接或刷新页面,就会出现登录页面。 但是他可以看到应用程序最后一页的信息。
这是用 symfony 防止这种行为的一种方法吗? BR...
security:
encoders:
App\Entity\Usuario:
algorithm: bcrypt
# 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\Usuario
property: usuario
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: lazy
provider: app_user_provider
form_login:
login_path: sac_login
check_path: sac_login
csrf_token_generator: security.csrf.token_manager
default_target_path: sac_login
always_use_default_target_path: true
logout:
path: sac_logout
guard:
authenticators:
- App\Security\LoginFormAuthenticator
# 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: ^/admin, roles: ROLE_ADMIN }
- { path: ^/sala, roles: ROLE_SALA }
- { path: ^/estacionario, roles: ROLE_ESTACIONARIO }
- { path: ^/registro, roles: ROLE_REGISTRO }
- { path: ^/direccion, roles: ROLE_DIRECTIVO }
- { path: ^/transcripcion, roles: ROLE_TRANSCRIPCION }
- { path: ^/reprografia, roles: ROLE_REPROGRAFIA }
PD1:Bossman回答后用户可以注销并点击浏览器返回按钮,登录页面停留,但是如果另一个不同角色的用户登录会出现错误403,因为应用程序重定向到我们应该避免的url .
PD2:应用程序没有不安全区域,所有用户都需要登录才能访问他们的工作区域。 我通过在用户表中保存该区域的路由并在 symfony 身份验证系统到达 onAuthenticationSuccess 时使用以下代码加载它来实现这一点:
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) {
return new RedirectResponse($targetPath);
}
$user = $this->entityManager->getRepository(Usuario::class)->findOneBy(['usuario' => $request->request->get('_username')]);
$ruta = $user->getRuta();
return new RedirectResponse($this->urlGenerator->generate($ruta));
}
这是浏览器的正常行为,但如果您真的需要控制它,那么您可以通过事件侦听器并设置响应标头来实现这一点,这样这些页面就不会被浏览器缓存。
此侦听器将仅根据控制器设置标题,因此您可以仅为管理页面设置它,例如App\Controller\AdminController
...
将文件放在src/EventListener/ResponseHeaderListener.php
中。
// src/EventListener/ResponseHeaderListener.php
namespace App\EventListener;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use App\Controller\AdminController;
class ResponseHeaderListener implements EventSubscriberInterface
{
private $controller;
public static function getSubscribedEvents()
{
return array(
'kernel.controller' => 'onKernelController',
'kernel.response' => 'onKernelResponse'
);
}
public function onKernelController(ControllerEvent $event)
{
$this->controller = $event->getController();
}
public function onKernelResponse(ResponseEvent $event)
{
if (!$event->isMasterRequest() || !is_array($this->controller)) {
return;
}
if ($this->controller[0] instanceof AdminController) {
$response = $event->getResponse();
// Set response headers
$response->headers->add(array(
'Cache-Control' => 'nocache, no-store, max-age=0, must-revalidate',
'Pragma' => 'no-cache'
));
}
}
}
根据您的需要进行调整和修改。
为了完成我想要的,首先我需要根据 Bossman 的回答创建 de ResponseHeaderListener类,但由于我的系统没有不安全区域,所以需要稍作改动,所有控制器都需要通过侦听器:
<?php
namespace App\EventListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
class ResponseHeaderListener implements EventSubscriberInterface
{
private $controller;
public static function getSubscribedEvents()
{
return array(
'kernel.controller' => 'onKernelController',
'kernel.response' => 'onKernelResponse'
);
}
public function onKernelController(ControllerEvent $event)
{
$this->controller = $event->getController();
}
public function onKernelResponse(ResponseEvent $event)
{
if (!$event->isMasterRequest() || !is_array($this->controller)) {
return;
}
$response = $event->getResponse();
$response->headers->add(array(
'Cache-Control' => 'nocache, no-store, max-age=0, must-revalidate',
'Pragma' => 'no-cache'
));
}
}
其次,在主防火墙下使用以下密钥更新security.yaml文件:
form_login:
login_path: sac_login
check_path: sac_login
always_use_default_target_path: true
其中sac_login是到登录页面的 symfony 路由。
第三步也是最后一步,注释或删除以下代码:
if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) {
return new RedirectResponse($targetPath);
}
在属于loginFormAuthenticator类的onAuthenticationSuccess函数中。
希望这个答案可以帮助其他有类似疑问的人。 真的,我读到了这个问题,不仅在 symfony 中,而且几天来我都在努力寻找解决方案。 感谢@Bossman 的所有耐心,当然还有他的帮助!!!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.