Wie leite ich einen anonymen Benutzer nach einem 403-Fehler zum Anmeldeformular um?

13

Ich möchte einen anonymen Benutzer zum Anmeldeformular umleiten, wenn dieser Benutzer auf einen 403-Fehler stößt.

Ich habe einen Ereignis-Abonnenten erstellt und dies ist mein Code, aber ich lande in einer Schleife auf der aktuellen Seite.

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

Ich denke, das hängt damit zusammen, dass die Antwort bereits das Ziel (aktuelle URL) enthält und System.404 und System.403 eine hohe Priorität haben, die mich daran hindert, dies außer Kraft zu setzen.

Pierre.Vriens
quelle
Können Sie Ihre gesamte Klasse anstelle nur der Methode hinzufügen?
googletorp
Es gibt nur $ events [KernelEvents :: REQUEST] = 'checkLoginNeeded'; in der Methode getSubscribedEvents ().

Antworten:

13

Der einfachste Weg ist zu durchsuchen zu /admin/config/system/site-informationund füllen Sie das Feld , das liest Default 403 (access denied) pagemituser/login

Kartagis
quelle
7
Das ist eine gute Lösung, berücksichtigt aber nicht die Tatsache, dass der Benutzer möglicherweise bereits angemeldet ist, was ich in der Beschreibung erwähnt habe.
13

Ich habe gesehen, dass diese Frage nie programmatisch beantwortet wurde. Der Code funktioniert tatsächlich, wenn er in einem Ausnahmeabonnement abgelegt wird:

/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
quelle
4
Dies funktioniert und ist wahrscheinlich die beste Antwort, bis die relevanten Module (einschließlich Regeln) stabile Releases haben. Ich musste -> toString () zu $ ​​query ['destination'] = Url :: fromRoute ('<current>') hinzufügen, damit dies funktioniert
Colin Shipton
2
Diese Antwort verdient es, höher zu erscheinen!
pbonnefoi
9

Wenn Sie sich nur den Titel dieser Frage ansehen (= Wie leite ich den Benutzer von 403 aus zum Anmeldeformular um? ), Gibt es zwei Möglichkeiten, dies zu tun, ohne dass ein benutzerdefinierter Code erforderlich ist (siehe unten).

Option 1: Verwenden Sie das CustomError-Modul

Mit dem CustomError- Modul kann der Site-Administrator benutzerdefinierte Fehlerseiten für die HTTP-Statuscodes 403 (Zugriff verweigert) und 404 (nicht gefunden) erstellen, ohne Knoten für jeden von ihnen zu erstellen. Einige weitere Details zu seinen Funktionen (von seiner Projektseite):

  • Konfigurierbarer Seitentitel und Beschreibungen.
  • Es gibt keine Autoren- und Datums- / Uhrzeit-Header wie bei normalen Knoten.
  • Jeder HTML-formatierte Text kann in den Seitenkörper eingefügt werden.
  • Die Fehlerseiten können thematisiert werden.
  • Benutzer, die nicht angemeldet sind und versuchen, auf einen Bereich zuzugreifen, für den eine Anmeldung erforderlich ist, werden nach der Anmeldung auf die Seite umgeleitet, auf die sie zugreifen wollten.
  • Ermöglicht benutzerdefinierte Weiterleitungen für 404s.

Sie interessieren sich wahrscheinlich hauptsächlich für den Teil " Benutzer, die nicht angemeldet sind und versuchen, auf einen Bereich zuzugreifen, für den eine Anmeldung erforderlich ist, werden nach der Anmeldung zu der Seite umgeleitet, auf die sie zugreifen wollten. "

Für D8 ist auch eine 8.x-1.x-dev-Version für dieses Modul verfügbar. Weitere Informationen hierzu finden Sie in Ausgabe 2219227 .

Option 2: Verwenden Sie das Modul Regeln

Angenommen, der Pfad der Seite "Standard 403" lautet no_access(über admin). Erstellen Sie dann eine Regel mit dem Modul Regeln , und geben Sie als Ereignis "Nach dem Besuch des Knotens no_access" ein. Damit die gesamte Regel ungefähr so ​​aussieht:

  • Ereignisse: Nach dem Besuch des Knotensno_access
  • Bedingungen:

    1. Benutzer hat Rolle (n) -Parameter: User: [site:current-user], Roles: anonymous user
    2. NICHT Textvergleich -Parameter: Text: [site:current-page:url], Matching text: user/login
  • Aktionen: Seitenumleitung -Parameter: URL: user/login

Wenn Sie dies möchten, können Sie sogar eine weitere Aktion hinzufügen, um auch eine (informative) Nachricht im Drupal-Nachrichtenbereich anzuzeigen, z. B. "Sie haben versucht, eine Seite zu besuchen, für die eine Anmeldung erforderlich ist ...".

Richtig, möglicherweise müssen Sie ein zusätzliches Modul ( Regeln ) aktivieren . Wie die wachsende Popularität des Moduls zeigt, ist dieses wahrscheinlich bereits in fast jeder Site aktiviert (ähnlich wie das Views- Modul), da es Dutzende Anwendungsfälle für dieses Modul gibt.

Für D8 gibt es eine 8.x-3.x-alfa1- Version für dieses Modul. Weitere Informationen zu seiner D8-Version finden Sie in Ausgabe 2574691 , die einen Link zur Regelausgabe " Rules 8.x Roadmap " enthält.

Wenn das oben Genannte nicht hilft, möchten Sie möglicherweise überprüfen, ob der Grund für Ihre Schleife (oder "eine hohe Priorität" wie in Ihrer Frage) nicht durch etwas ähnliches wie die Antwort auf die Frage " Wie spezifizieren " verhindert / erklärt werden kann Ein Regelereignis wie "Inhalt wird angezeigt"? ".

Pierre.Vriens
quelle
4

Ich denke, die Lösung für Ihr Problem ist einfach. Sie können ganz einfach eine benutzerdefinierte Seite für diese Seite erstellen 404und 403dann anonyme Benutzer auf diese Seite umleiten /user.

Sie können diesen Code verwenden

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

Wann immer 404 auftritt, wird Ihr page--404.tpl.phpverwendet. Verwenden Sie auf dieser Seite diesen Code

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

Auf der Seite Erstellen von benutzerdefinierten 403- und 404-Seiten in Drupal wird eine weitere Methode zum Erstellen einer Seite für 403und erläutert 404.

M ama D
quelle
5
Hey Kumpel, du solltest die Tags und den Code überprüfen. Dieser Typ verwendet eindeutig Drupal 8.
alexej_d
1
Hallo, ich habe ihm den Algorithmus gegeben, er kann ihn leicht in das 8Format ändern
M ama D
3

Am einfachsten geht das mit dem Redirect 403 to User Login- Modul (für D8 gibt es eine Dev-Version davon). Hier ist ein Zitat darüber (von seiner Projektseite):

Leiten Sie die HTTP 403-Fehlerseite mit der folgenden optionalen Meldung auf die Drupal / user / login-Seite um:

"Zugriff verweigert! Sie müssen sich anmelden, um diese Seite anzuzeigen."

Außerdem wird die gewünschte Seite an die URL-Abfragezeichenfolge angehängt, sodass der Benutzer nach erfolgreicher Anmeldung direkt dorthin weitergeleitet wird, wo er ursprünglich versucht hatte.

Marco.b
quelle
1
Warum wurde diese Antwort abgelehnt?
Miloš Kroulík
@ milos.kroulik Ich denke, weil die Frage über Drupal 8 ist, aber dieses Modul ist für 7und6
M ama D
1
Nein, das Modul hat eine Drupal 8-Version in der Entwicklung
Colin Shipton
1
Ich bin mir ziemlich sicher, dass es sich beim Downvote um eine "Nur-Link" -Antwort handelte (ein typischer Grund für das Downvoten oder sogar das Löschen von Antworten ...). Solche Antworten werden in der Regel auch in der Überprüfungswarteschlange "Antworten mit niedriger Qualität" angezeigt. In meiner bearbeiteten Version dieser Antwort finden Sie jetzt eine erweiterte Version dieser Antwort (die nicht mehr als Antwort nur auf einen Link zu betrachten ist).
Pierre.Vriens
Diese Antwort berücksichtigt nicht, ob der Benutzer bereits angemeldet ist oder ob die Site fast404 und 403 verwendet.
0

(1) Erstellen Sie einen Seitenknoten mit einem Alias ​​"/my403.html".

(2) Gehen Sie zu / admin / config / system / site-information und setzen Sie "/my403.html" als 403-Errorpage

(3) Gehen Sie zu / admin / structure / block und fügen Sie den Block "Benutzeranmeldung" (Sec. Forms) zum Hauptinhaltsbereich hinzu. Beschränken Sie das Erscheinungsbild des Blocks auf die Seite "my403.html" und die Rolle "guest".

Das ist es.

Wenn Sie mehr Kontrolle benötigen, erstellen Sie einen Controller für Ihre 403-Seite und fügen Sie das UserLoginForm manuell hinzu.

Viele Grüße, Rainer

Rainer Feike
quelle