Quelle est la meilleure façon de notifier un utilisateur après une redirection d'une règle de contrôle d'accès?

à Partir de Symfony 2.3 Sécurité docs:

Si l'accès est refusé, , le système va tenter d'authentifier l'utilisateur si ce n'est déjà (par exemple, rediriger l'utilisateur vers la page de connexion) . Si l'utilisateur est déjà connecté, la 403 "accès refusé" page d'erreur sera affiché. Voir Comment personnaliser les Pages d'Erreur pour plus d'informations.

j'utilise actuellement une règle access_control pour peu de routes. Je voudrais informer un utilisateur anonyme s'ils sont redirigés vers la route de connexion avec un message comme vous devez vous connecter pour accéder à cette page ."J'ai lu les documents de sécurité à quelques reprises et je n'ai rien trouvé de pertinent à ce sujet. Suis-je surplombant quelque chose?

si non, quelle serait la meilleure façon d'informer l'utilisateur quand il est arrêté par une access_control règle seulement s'il est redirigé vers login (i.e. pas s'ils sont juste dans un rôle non autorisé )?

EDIT: Pour clarifier, je demande spécifiquement comment vérifier si une redirection a été causée par une règle access_control (de préférence en brindille si possible).

20
demandé sur Carrie Kendall 2013-07-02 19:00:38

3 réponses

Alors, après un peu de recherche, j'ai trouvé la bonne façon de le faire. Vous devrez utiliser un service Entry Point et le définir dans votre configuration de pare-feu.

cette méthode ne modifiera pas avec votre page par défaut paramètres spécifiés dans votre configuration pare-feu pour la connexion.


Le Code

sécurité.yml:

firewalls:
    main:
        entry_point: entry_point.user_login #or whatever you name your service
        pattern: ^/
        form_login:
        # ...

src/Acme/UserBundle/config/services.yml

services:
    entry_point.user_login:
        class: Acme\UserBundle\Service\LoginEntryPoint
        arguments: [ @router ] #I am going to use this for URL generation since I will be redirecting in my service

src/Acme/UserBundle/Service/LoginEntryPoint.php:

namespace Acme\UserBundle\Service;

use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface,
    Symfony\Component\Security\Core\Exception\AuthenticationException,
    Symfony\Component\HttpFoundation\Request,
    Symfony\Component\HttpFoundation\RedirectResponse;

/**
 * When the user is not authenticated at all (i.e. when the security context has no token yet), 
 * the firewall's entry point will be called to start() the authentication process. 
 */
class LoginEntryPoint implements AuthenticationEntryPointInterface
{
    protected $router;

    public function __construct($router)
    {
        $this->router = $router;
    }

    /*
     * This method receives the current Request object and the exception by which the exception 
     * listener was triggered. 
     * 
     * The method should return a Response object
     */
    public function start(Request $request, AuthenticationException $authException = null)
    {
        $session = $request->getSession();

        // I am choosing to set a FlashBag message with my own custom message.
        // Alternatively, you could use AuthenticaionException's generic message 
        // by calling $authException->getMessage()
        $session->getFlashBag()->add('warning', 'You must be logged in to access that page');

        return new RedirectResponse($this->router->generate('login'));
    }
}

login.HTML.brindille:

{# bootstrap ready for your convenience ;] #}
{% if app.session.flashbag.has('warning') %}
    {% for flashMessage in app.session.flashbag.get('warning') %}
        <div class="alert alert-warning">
            <button type="button" class="close" data-dismiss="alert">&times;</button>
            {{ flashMessage }}
        </div>
    {% endfor %}
{% endif %}

ressources:

56
répondu Carrie Kendall 2018-09-02 00:42:55

je pense qu'un kernel.exception écouter et définir un message flash peut le faire. Exemple non testé:

use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;

class My403ExceptionListener
{
    protected $session;

    public function __construct(SessionInterface $session)
    {
        $this->session = $session;
    }

    public function onKernelException(GetResponseForExceptionEvent $event)
    {
        $exception = $event->getException();
        if ($exception instanceof AccessDeniedHttpException) {
            $this->session->getFlashBag()->set('warning', 'You must login to access that page.');
        }
    }
}

Ne sais pas vraiment si ça fonctionne ou si c'est la bonne chose. Vous pouvez l'enregistrer comme kernel.event_listener . Ou peut-être est-il préférable de choisir un service dédié et de le Définir comme paramètre de access_denied_handler dans la firewall config . Je pense qu'il y a plusieurs façons possibles.

1
répondu Emii Khaos 2013-07-02 17:07:32

ne pourriez-vous pas simplement avoir deux itinéraires de connexion?

par exemple, dans la configuration de sécurité

form_login:
    login_path: /login_message

dans votre contrôleur de connexion

/**
 * @Template()
 * @Route("/notauthorized", name="login_message")
 */
 public function loginMessageAction()
 {
    return [];
 }

et ensuite dans votre loginMessage.HTML.TGV

<a href="{{ path('login') }}">You must login to access this page.</a>
0
répondu Kris 2013-07-02 16:29:26