Як перенаправити анонімного користувача до форми для входу після помилки 403?


13

Я хочу перенаправити анонімного користувача до форми для входу, якщо такий користувач виявить помилку 403.

Я створив підписника події, і це мій код, але я опиняюся на циклі на поточній сторінці.

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

Я думаю, що це пов'язано з тим, що відповідь вже містить призначення (поточний uri) та system.404 та system.403 мають високий пріоритет, який заважає мені це перекрити.


Чи можете ви додати весь свій клас замість просто методу?
googletorp

Є лише $ події [KernelEvents :: ЗАПИТАННЯ] = 'checkLoginNeeded'; у методі getSubscribedEvents ().

Відповіді:


14

Я бачив, що на це питання ніколи не відповідали, як це зробити програмно. Код насправді спрацьовує, розміщуючи його в передплатнику винятку:

/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
Це працює і, мабуть, найкраща відповідь, поки відповідні модулі (включені правила) не мають стабільних версій. Мені довелося додати -> toString () до $ query ['призначення'] = Url :: fromRoute ('<поточний>'), щоб це працювало
Colin Shipton

2
Ця відповідь заслуговує на показ вище!
pbonnefoi

13

Найпростіший спосіб , щоб перейти до /admin/config/system/site-informationі заповнення в поле , яке зчитує Default 403 (access denied) pageзuser/login


7
Це хороше рішення, але воно не враховує того факту, що користувач може вже увійти в систему, про що я згадував в описі.

9

Просто дивлячись на заголовок цього питання (= Як перенаправити користувача для входу в форму з 403? ), Є два варіанти зробити це без будь-якого спеціального коду, як детально описано нижче.

Варіант 1: Використовуйте модуль CustomError

Модуль CustomError дозволяє адміністратору сайту створювати власні сторінки помилок для кодів статусів HTTP 403 (доступ заборонено) та 404 (не знайдено), не створюючи вузлів для кожного з них. Ще кілька деталей про його функції (зі сторінки проекту):

  • Настроювана назва сторінки та описи.
  • Немає заголовків автора та дати / часу, як у звичайних вузлах.
  • Будь-який текст у форматі HTML може бути розміщений у тілі сторінки.
  • Сторінки помилок можна відключити.
  • Користувачі, які не ввійшли та намагаються отримати доступ до області, яка потребує входу, будуть перенаправлені на сторінку, до якої намагалися отримати доступ після входу.
  • Дозволяє користувацькі переадресації протягом 404 секунд.

Напевно, вас зацікавить найбільше частина про " Користувачі, які не ввійшли в систему та намагаються отримати доступ до області, яка вимагає входу, буде перенаправлена ​​на сторінку, до якої вони намагалися отримати доступ після входу. "

Для D8 також доступна версія 8.x-1.x-dev для цього модуля, більш детальну інформацію про нього можна знайти у Випуску №2219227 .

Варіант 2: Використовуйте модуль Правила

Припустимо, для сторінки сторінки "За замовчуванням 403" встановлено значення no_access(через адміністратор). Потім створіть правило, використовуючи модуль Правила , в якості події щось подібне до "Після відвідування вузла no_access". Щоб все правило виглядало приблизно так:

  • Події: Після відвідування вузлаno_access
  • Умови:

    1. Користувач має ролі (и) -Parameter: User: [site:current-user], Roles: anonymous user
    2. НЕ Порівняння тексту -Parameter: Text: [site:current-page:url], Matching text: user/login
  • Дії: переспрямування сторінки -Parameter: URL: user/login

Якщо ви хочете зробити це, ви можете навіть додати ще одну дію, щоб також відобразити якесь (інформаційне) повідомлення в області повідомлень Drupal, з таким кшталт "Ви намагалися відвідати сторінку, для якої потрібно ввійти ...".

Правда, може знадобитися увімкнути додатковий модуль ( Правила ). Але, на що вказує і його зростаюча популярність, цей модуль, ймовірно, вже ввімкнено в основному на будь-якому сайті (подібний до модуля Views ), оскільки для цього модуля є десятки випадків використання.

Для D8 є версія 8.x-3.x-alfa1 для цього модуля, також більш детальну інформацію про його версію D8 можна знайти у випуску №2574691 , який містить посилання на випуск Правил " Правила 8.x Дорожня карта "

Якщо вищезазначене не допомагає, то, можливо, ви захочете перевірити, чи не можна запобігти / пояснити причину вашого циклу (або "якийсь високий пріоритет", як у вашому запитанні) чимось подібним до відповіді на питання " Як вказати a Подія Правил типу "Вміст" буде "переглянуто"? ".


4

Я думаю, що рішення вашої проблеми є простим. Ви можете легко створити користувацьку сторінку для, 404а 403потім всередині цієї сторінки, перенаправити анонімних користувачів на /userсторінку.

Ви можете використовувати цей код

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

Кожного разу, коли відбудеться 404, ви page--404.tpl.phpбудете використані. На цій сторінці використовуйте цей код

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

Як зробити замовлення 403 і 404 сторінки в Drupal пояснює інший спосіб створення сторінки для 403і 404.


5
Ей, приятелю, ти повинен перевірити теги та код. Цей хлопець явно використовує Drupal 8.
alexej_d

1
привіт, я дав йому алгоритм, він може легко змінити його на 8формат
M ama D

3

Найпростіший спосіб зробити це - використовувати модуль переадресації 403 на вхід користувача (версія Dv існує для D8). Ось цитата про це (зі сторінки проекту):

Перенаправити сторінку помилки HTTP 403 на сторінку Drupal / користувач / вхід з додатковим повідомленням:

"Доступ заборонено! Ви повинні увійти, щоб переглянути цю сторінку."

Крім того, бажана сторінка додається у рядок запиту URL, так що після успішного входу користувач переноситься безпосередньо туди, куди вони спочатку намагалися піти.


1
Чому ця відповідь спростована?
Miloš Kroulík

@ Milos.kroulik я припускаю , тому що мова йде про Drupal 8 , але цей модуль для 7і6
М ама D

1
Немає цього модуля в розробці версії Drupal 8
Колін Шиптон

1
Досить впевнений, що нижченаведена стаття була через те, що відповідь була "лише посиланням", відповідь (типова причина, коли відповіді занижуються або навіть видаляються ...). Такі відповіді, як правило, також відображаються у черзі на огляд "низької якості". Відповіді на мою відредаговану версію цієї відповіді див. Зараз для розширеного перегляду її (більше не ризикуючи вважати лише відповіддю посилання).
Pierre.Vriens

Ця відповідь не враховується, якщо користувач уже ввійшов у систему або якщо сайт використовує fast404 та 403.

0

(1) створити вузол сторінки з псевдонімом типу "/my403.html"

(2) перейдіть до / admin / config / system / site-information та встановіть "/my403.html" як 403-Errorpage

(3) перейдіть до / admin / structure / block та додайте блок "реєстрація користувача" (Sec. Forms) до основної області вмісту. Обмежте зовнішній вигляд блоку на сторінці "my403.html" та ролі "гість".

Це воно.

Якщо вам потрібен додатковий контроль, створіть контролер для вашої сторінки 403 та додайте UserLoginForm вручну.

З найкращими побажаннями, Райнер

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.