Comment rediriger un utilisateur anonyme vers le formulaire de connexion après une erreur 403?

13

Je souhaite rediriger un utilisateur anonyme vers le formulaire de connexion si cet utilisateur rencontre une erreur 403.

J'ai créé un abonné aux événements et voici mon code, mais je me retrouve en boucle sur la page actuelle.

/**
   * Redirect anonymous user to login page if he encounters 404 or 403
   * response.
   *
   * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $response
   *   The created response object that will be returned.
   * @param string $event
   *   The string representation of the event.
   * @param \Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher $event_dispatcher
   *   Event dispatcher that lazily loads listeners and subscribers from the dependency injection
   *   container.
   */
  public function checkLoginNeeded(GetResponseEvent $response, $event, ContainerAwareEventDispatcher $event_dispatcher) {
    $routeMatch = RouteMatch::createFromRequest($response->getRequest());
    $route_name = $routeMatch->getRouteName();
    $is_anonymous = \Drupal::currentUser()->isAnonymous();
    $is_not_login = $route_name != 'user.login';

    if ($is_anonymous && $route_name == 'system.403' && $is_not_login) {
      $query = $response->getRequest()->query->all();
//      $query['destination'] = $routeMatch->getRouteObject()->getPath();
      $query['destination'] = \Drupal::url('<current>');
      $login_uri = \Drupal::url('user.login', [], ['query' => $query]);
      $returnResponse = new RedirectResponse($login_uri, Response::HTTP_FOUND);
      $response->setResponse($returnResponse);
    }
  }

Je pense que cela est lié au fait que la réponse contient déjà la destination (uri actuel) et system.404 et system.403 ont une haute priorité qui m'empêche de passer outre.

Pierre.Vriens
la source
Pouvez-vous ajouter votre classe entière au lieu de simplement la méthode?
googletorp
Il n'y a que $ events [KernelEvents :: REQUEST] = 'checkLoginNeeded'; dans la méthode getSubscribedEvents ().

Réponses:

14

J'ai vu qu'il n'a jamais été répondu à cette question comment procéder par programme. Le code fonctionne réellement, lorsqu'il est placé dans un abonné d'exception:

/src/EventSubscriber/RedirectOn403Subscriber.php:

<?php

namespace Drupal\mymodule\EventSubscriber;

use Drupal\Core\EventSubscriber\HttpExceptionSubscriberBase;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;

class RedirectOn403Subscriber extends HttpExceptionSubscriberBase {

  protected $currentUser;

  public function __construct(AccountInterface $current_user) {
    $this->currentUser = $current_user;
  }

  protected function getHandledFormats() {
    return ['html'];
  }

  public function on403(GetResponseForExceptionEvent $event) {
    $request = $event->getRequest();
    $is_anonymous = $this->currentUser->isAnonymous();
    $route_name = $request->attributes->get('_route');
    $is_not_login = $route_name != 'user.login';
    if ($is_anonymous && $is_not_login) {
      $query = $request->query->all();
      $query['destination'] = Url::fromRoute('<current>')->toString();
      $login_uri = Url::fromRoute('user.login', [], ['query' => $query])->toString();
      $returnResponse = new RedirectResponse($login_uri);
      $event->setResponse($returnResponse);
    }
  }

}

mymodule.services.yml:

services:
  mymodule.exception403.subscriber:
    class: Drupal\mymodule\EventSubscriber\RedirectOn403Subscriber
    tags:
      - { name: event_subscriber }
    arguments: ['@current_user']
4k4
la source
4
Cela fonctionne et est probablement la meilleure réponse jusqu'à ce que les modules pertinents (règles incluses) aient des versions stables. J'ai dû ajouter -> toString () à $ query ['destination'] = Url :: fromRoute ('<current>') pour que cela fonctionne
Colin Shipton
2
Cette réponse mérite de se montrer plus haut!
pbonnefoi
13

Le moyen le plus simple est de parcourir /admin/config/system/site-informationet de remplir le champ qui se lit Default 403 (access denied) pageavecuser/login

Kartagis
la source
7
C'est une bonne solution mais elle ne tient pas compte du fait que l'utilisateur est peut-être déjà connecté comme je l'ai mentionné dans la description.
9

En regardant simplement le titre de cette question (= Comment rediriger l'utilisateur vers le formulaire de connexion à partir de 403? ), Il y a 2 options pour le faire, sans aucun code personnalisé impliqué, comme détaillé ci-dessous.

Option 1: utilisez le module CustomError

Le module CustomError permet à l'administrateur du site de créer des pages d'erreur personnalisées pour les codes d'état HTTP 403 (accès refusé) et 404 (introuvable), sans créer de nœuds pour chacun d'eux. Quelques détails supplémentaires sur ses fonctionnalités (à partir de sa page de projet):

  • Titre et descriptions des pages configurables.
  • Il n'y a pas d'en-tête auteur et date / heure comme avec les nœuds normaux.
  • Tout texte au format HTML peut être placé dans le corps de la page.
  • Les pages d'erreur sont thématiques.
  • Les utilisateurs qui ne sont pas connectés et tentent d'accéder à une zone nécessitant une connexion seront redirigés vers la page à laquelle ils tentaient d'accéder après leur connexion.
  • Permet des redirections personnalisées pour 404s.

Vous serez probablement intéressé principalement par la partie " Les utilisateurs qui ne sont pas connectés et tentent d'accéder à une zone qui nécessite une connexion seront redirigés vers la page à laquelle ils tentaient d'accéder après leur connexion. ".

Pour D8, il existe également une version 8.x-1.x-dev pour ce module, plus de détails à ce sujet peuvent être trouvés dans le numéro # 2219227 .

Option 2: utilisez le module Règles

Supposons que le chemin de la page "403 par défaut" est défini sur no_access(via admin). Créez ensuite une règle à l'aide du module Règles , avec comme événement quelque chose comme "Après avoir visité le nœud no_access". Pour que la règle entière ressemble à ceci:

  • Événements: après avoir visité le nœudno_access
  • Conditions:

    1. L'utilisateur a un ou plusieurs rôles -Parameter: User: [site:current-user], Roles: anonymous user
    2. PAS de comparaison de texte -Parameter: Text: [site:current-page:url], Matching text: user/login
  • Actions: Redirection de page -Parameter: URL: user/login

Si vous le souhaitez, vous pouvez même ajouter une autre action pour afficher également un message (informatif) dans la zone de message Drupal, avec quelque chose comme "Vous avez essayé de visiter une page pour laquelle une connexion est requise ...".

Certes, cela peut vous obliger à activer un module supplémentaire contribué ( règles ). Mais, comme l'indique également sa popularité croissante, ce module est probablement déjà activé dans la plupart des sites (similaire au module Views ), car il existe des dizaines de cas d'utilisation pour ce module.

Pour D8, il existe également une version 8.x-3.x-alfa1 pour ce module, plus de détails sur sa version D8 peuvent être trouvés dans le numéro 2574691 , qui inclut un lien vers le problème de règles " Rules 8.x Roadmap "

Si ce qui précède ne vous aide pas, vous voudrez peut-être vérifier si la raison de votre boucle (ou "une priorité élevée" comme dans votre question) ne peut pas être empêchée / expliquée par quelque chose de similaire à la réponse à la question " Comment spécifier un événement de règles tel que "Le contenu sera" affiché "? ".

Pierre.Vriens
la source
4

Je suppose que la solution à votre problème est simple. Vous pouvez facilement créer une page personnalisée pour 404, 403puis à l'intérieur de cette page, rediriger les utilisateurs anonymes vers la /userpage.

Vous pouvez utiliser ce code

function YOURTHEME_preprocess_page(&$vars) {
   $header = drupal_get_http_header('status'); 
   if ($header == '404 Not Found') {     
       $vars['theme_hook_suggestions'][] = 'page__404';
   }
}

Chaque fois que 404 se produit, vous page--404.tpl.phpserez utilisé. Dans cette page, utilisez ce code

if(user_is_logged_in() == false){
       /// You can do anything here.
}

La page Comment créer des pages 403 et 404 personnalisées dans Drupal explique une autre méthode de création d'une page pour 403et 404.

M ama D
la source
5
Hé mec, tu devrais vérifier les balises et le code. Ce gars utilise clairement Drupal 8.
alexej_d
1
salut, je lui ai donné l'algorithme, il peut facilement le changer au 8format
M ama D
3

La façon la plus simple de le faire est d'utiliser le module Rediriger 403 vers la connexion utilisateur (une version de développement de celui-ci existe pour D8). Voici une citation à ce sujet (à partir de sa page de projet):

Redirigez la page d'erreur HTTP 403 vers la page Drupal / utilisateur / connexion avec un message facultatif qui se lit comme suit:

"Accès refusé! Vous devez vous connecter pour voir cette page."

En outre, la page souhaitée est ajoutée dans la chaîne de requête URL de sorte que, une fois la connexion réussie, l'utilisateur est redirigé directement là où il essayait initialement d'aller.

Marco.b
la source
1
Pourquoi cette réponse est-elle rejetée?
Miloš Kroulík
@ milos.kroulik Je suppose que parce que la question concerne Drupal 8 mais ce module est pour 7et6
M ama D
1
Non, ce module a une version Drupal 8 en développement
Colin Shipton
1
Je suis presque sûr que le downvote était dû au fait que la réponse était une réponse "link-only" (une raison typique pour les réponses étant downvotées, ou même supprimées ...). De telles réponses apparaissent généralement également dans la file d'attente de révision des «réponses de faible qualité» ... Reportez-vous à ma version modifiée de cette réponse maintenant pour une version améliorée de celle-ci (plus à risque d'être considérée comme une réponse de lien uniquement).
Pierre.Vriens
Cette réponse ne prend pas en compte si l'utilisateur est déjà connecté ou si le site utilise fast404 et 403.
0

(1) créer un nœud de page avec un alias comme "/my403.html"

(2) allez dans / admin / config / system / site-information et définissez "/my403.html" comme 403-Errorpage

(3) allez dans / admin / structure / block et ajoutez le bloc "User login" (Sec. Forms) à la zone de contenu principale. Limitez l'apparence du bloc à la page "my403.html" et au rôle "invité".

C'est ça.

Si vous avez besoin de plus de contrôle, créez un contrôleur pour votre page 403 et ajoutez manuellement UserLoginForm.

Cordialement, Rainer

Rainer Feike
la source