Come reindirizzare un utente anonimo al modulo di accesso dopo un errore 403?


13

Voglio reindirizzare un utente anonimo al modulo di accesso se tale utente rileva un errore 403.

Ho creato l'abbonato all'evento e questo è il mio codice, ma finisco su loop nella pagina corrente.

/**
   * 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);
    }
  }

Penso che ciò sia correlato al fatto che la risposta contiene già destinazione (uri corrente) e system.404 e system.403 hanno una priorità elevata che mi impedisce di ignorarlo.


Puoi aggiungere l'intera classe anziché solo il metodo?
googletorp

Esistono solo $ events [KernelEvents :: REQUEST] = 'checkLoginNeeded'; nel metodo getSubscribedEvents ().

Risposte:


14

Ho visto che a questa domanda non è mai stata data risposta come farlo a livello di codice. Il codice effettivamente funziona, se inserito in un Sottoscrittore di eccezioni:

/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']

4
Funziona ed è probabilmente la risposta migliore fino a quando i moduli pertinenti (regole incluse) non avranno versioni stabili. Ho dovuto aggiungere -> toString () a $ query ['destination'] = Url :: fromRoute ('<current>') per farlo funzionare
Colin Shipton,

2
Questa risposta merita di apparire più in alto!
pbonnefoi,

13

Il modo più semplice è quello di navigare a /admin/config/system/site-informatione compilare il campo che legge Default 403 (access denied) pageconuser/login


7
Questa è una buona soluzione, ma non tiene conto del fatto che l'utente potrebbe aver già effettuato l'accesso, di cui ho parlato nella descrizione.

9

Basta guardare il titolo di questa domanda (= Come reindirizzare l'utente al modulo di login da 403? ), Ci sono 2 opzioni per farlo, senza alcun codice personalizzato, come descritto di seguito.

Opzione 1: utilizzare il modulo CustomError

Il modulo CustomError consente all'amministratore del sito di creare pagine di errore personalizzate per i codici di stato HTTP 403 (accesso negato) e 404 (non trovato), senza creare nodi per ciascuno di essi. Alcuni ulteriori dettagli sulle sue caratteristiche (dalla sua pagina del progetto):

  • Titolo e descrizioni della pagina configurabili.
  • Non ci sono intestazioni autore e data / ora come nei nodi normali.
  • Qualsiasi testo in formato HTML può essere inserito nel corpo della pagina.
  • Le pagine di errore sono temabili.
  • Gli utenti che non hanno effettuato l'accesso e tentano di accedere a un'area che richiede l'accesso verranno reindirizzati alla pagina a cui stavano tentando di accedere dopo aver effettuato l'accesso.
  • Consente reindirizzamenti personalizzati per 404 secondi.

Probabilmente sarai interessato principalmente alla parte " Gli utenti che non hanno effettuato l'accesso e provano ad accedere a un'area che richiede l'accesso verranno reindirizzati alla pagina a cui stavano tentando di accedere dopo aver effettuato l'accesso ".

Per D8 è disponibile anche una versione 8.x-1.x-dev per questo modulo, maggiori dettagli a riguardo sono disponibili nel numero 2219227 .

Opzione 2: utilizzare il modulo Regole

Supponiamo che il percorso della pagina "Default 403" sia impostato su no_access(tramite admin). Quindi crea una regola usando il modulo Regole , con Evento qualcosa come "Dopo aver visitato il nodo no_access". In modo che l'intera regola sia simile a questa:

  • Eventi: dopo aver visitato il nodono_access
  • condizioni:

    1. L'utente ha un ruolo (i) -Parameter: User: [site:current-user], Roles: anonymous user
    2. NOT Confronto del testo -Parameter: Text: [site:current-page:url], Matching text: user/login
  • Azioni: reindirizzamento della pagina -Parameter: URL: user/login

Se vuoi farlo, potresti anche aggiungere un'altra Azione per visualizzare anche un messaggio (informativo) nell'area dei messaggi Drupal, con qualcosa come "Hai provato a visitare una pagina per la quale è richiesto il login ...".

È vero, potrebbe essere necessario abilitare un modulo aggiuntivo fornito ( Regole ). Ma, come indicato anche dalla sua crescente popolarità, quel modulo è probabilmente già abilitato in quasi tutti i siti (simile al modulo Views ), perché ci sono dozzine di casi d'uso per questo modulo.

Per D8 è disponibile anche una versione 8.x-3.x-alfa1 per questo modulo, maggiori dettagli sulla sua versione D8 sono disponibili nel numero 2574691 , che include un collegamento al problema delle regole " Regole 8.x Roadmap "

Se quanto sopra non aiuta, potresti voler verificare se il motivo del tuo ciclo (o "qualche priorità alta" come nella tua domanda) non può essere prevenuto / spiegato da qualcosa di simile alla risposta alla domanda " Come specificare un evento di regole come "Il contenuto" verrà "visualizzato"? ".


4

Immagino che la soluzione al tuo problema sia semplice. Puoi facilmente creare una pagina personalizzata per 404e 403quindi all'interno di questa pagina, reindirizzare gli utenti anonimi alla /userpagina.

Puoi usare questo codice

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

Ogni volta che si verifica 404, page--404.tpl.phpverrà utilizzato. In questa pagina usa questo codice

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

La pagina Come creare pagine 403 e 404 personalizzate in Drupal spiega un altro metodo per creare una pagina per 403e 404.


5
Ehi amico, dovresti controllare i tag e il codice. Questo ragazzo sta chiaramente usando Drupal 8.
alexej_d

1
ciao, gli ho dato l'algoritmo, può facilmente cambiarlo in 8formato
M ama D

3

Il modo più semplice per farlo è utilizzare il modulo Redirect 403 to User Login (ne esiste una versione dev per D8). Ecco una citazione a riguardo (dalla sua pagina del progetto):

Reindirizzare la pagina di errore HTTP 403 alla pagina Drupal / utente / login con un messaggio opzionale che recita:

"Accesso negato! Devi accedere per visualizzare questa pagina."

Inoltre, la pagina desiderata viene aggiunta nella stringa di query dell'URL in modo che, una volta effettuato l'accesso, l'utente venga portato direttamente dove stava tentando di andare originariamente.


1
Perché questa risposta è stata sottoposta a downgrade?
Miloš Kroulík,

@ milos.kroulik Immagino perché la domanda riguarda Drupal 8 ma quel modulo è per 7e6
M ama D

1
No, quel modulo ha una versione Drupal 8 in sviluppo
Colin Shipton,

1
Abbastanza sicuro che il downvote fosse dovuto al fatto che la risposta era una risposta "solo link" (un motivo tipico per cui le risposte venivano ridotte al voto o addirittura cancellate ...). Tali risposte di solito compaiono anche nella coda di recensioni "Risposte a bassa qualità" ... Fare riferimento alla mia versione modificata di questa risposta ora per una versione avanzata di essa (non rischia più di essere considerata come una risposta solo link).
Pierre.Vriens,

Questa risposta non prende in considerazione se l'utente è già registrato o se il sito utilizza fast404 e 403.

0

(1) crea un nodo di pagina con un alias come "/my403.html"

(2) vai su / admin / config / system / site-information e imposta "/my403.html" come 403-Errorpage

(3) vai su / admin / struttura / blocco e aggiungi il blocco "Accesso utente" (Moduli sec.) All'area di contenuto principale. Limita l'aspetto del blocco alla pagina "my403.html" e al ruolo "ospite".

Questo è tutto.

Se hai bisogno di maggiore controllo, crea un controller per la tua pagina 403 e aggiungi UserLoginForm manualmente.

Cordiali saluti, Rainer

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.