symfony 注销后避免浏览器后退按钮
avoid browser back button after symfony logout
我在 symfony 项目中工作。它几乎准备就绪,身份验证流程正常...但是在用户注销后,他可以通过按浏览器中的后退按钮返回系统。
用户无法使用该系统,如果他点击某些 link o 刷新页面,就会出现登录页面。但是他可以看到申请最后一页的信息。
这是一种使用 symfony 来防止这种行为的方法吗? BR...
security.yaml
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:老板回答后,用户可以注销并点击浏览器后退按钮,登录页面保持不变,但如果另一个角色不同的用户登录时会出现403错误,因为应用程序重定向到url 我们应该避免的。
PD2:应用程序没有不安全的区域,所有用户都需要登录才能访问他们的工作区域。我通过在用户 table 中保存该区域的路由并在 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));
}
这是浏览器的正常行为,但如果您确实需要控制它,则可以使用事件侦听器并设置响应来实现此目的 headers 这样浏览器就不会缓存这些页面.
此侦听器只会根据控制器设置 headers,因此您可以仅为管理页面设置它,例如 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 class 但是有一个小改动,因为我的系统没有不安全的区域,所有的控制器都需要通过监听器:
<?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);
}
在 onAuthenticationSuccess 函数中属于 loginFormAuthenticator class.
希望这个回答可以帮助到有类似疑问的人。真的,我不仅在 symfony 中读到过这个问题,而且几天来我一直在努力寻找解决方案。感谢@Bossman 的耐心等待,当然还有他的帮助!!!
我在 symfony 项目中工作。它几乎准备就绪,身份验证流程正常...但是在用户注销后,他可以通过按浏览器中的后退按钮返回系统。
用户无法使用该系统,如果他点击某些 link o 刷新页面,就会出现登录页面。但是他可以看到申请最后一页的信息。
这是一种使用 symfony 来防止这种行为的方法吗? BR...
security.yaml
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:老板回答后,用户可以注销并点击浏览器后退按钮,登录页面保持不变,但如果另一个角色不同的用户登录时会出现403错误,因为应用程序重定向到url 我们应该避免的。
PD2:应用程序没有不安全的区域,所有用户都需要登录才能访问他们的工作区域。我通过在用户 table 中保存该区域的路由并在 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));
}
这是浏览器的正常行为,但如果您确实需要控制它,则可以使用事件侦听器并设置响应来实现此目的 headers 这样浏览器就不会缓存这些页面.
此侦听器只会根据控制器设置 headers,因此您可以仅为管理页面设置它,例如 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 class 但是有一个小改动,因为我的系统没有不安全的区域,所有的控制器都需要通过监听器:
<?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);
}
在 onAuthenticationSuccess 函数中属于 loginFormAuthenticator class.
希望这个回答可以帮助到有类似疑问的人。真的,我不仅在 symfony 中读到过这个问题,而且几天来我一直在努力寻找解决方案。感谢@Bossman 的耐心等待,当然还有他的帮助!!!