繁体   English   中英

symfony 注销后避免浏览器返回按钮

[英]avoid browser back button after symfony logout

我在一个 symfony 项目中工作。 它几乎准备好了,身份验证流程很好......但是在用户注销后,他可以通过按浏览器中的后退按钮返回系统。

用户无法使用系统,如果他点击某个链接或刷新页面,就会出现登录页面。 但是他可以看到应用程序最后一页的信息。

这是用 symfony 防止这种行为的一种方法吗? BR...

安全.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: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.

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