Bagaimana cara mengarahkan pengguna anonim ke formulir login setelah kesalahan 403?

13

Saya ingin mengarahkan pengguna anonim ke formulir login jika pengguna tersebut menemukan kesalahan 403.

Saya telah membuat pelanggan acara dan ini adalah kode saya, tetapi saya berakhir di loop pada halaman saat ini.

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

Saya pikir ini terkait dengan fakta bahwa respons sudah berisi tujuan (uri saat ini) dan system.404 dan system.403 memiliki beberapa prioritas tinggi yang mencegah saya untuk menimpa ini.

Pierre
sumber
Bisakah Anda menambahkan seluruh kelas Anda bukan hanya metode?
googletorp
Hanya ada $ events [KernelEvents :: REQUEST] = 'checkLoginNeeded'; dalam metode getSubscribedEvents ().

Jawaban:

14

Saya telah melihat bahwa pertanyaan ini tidak pernah dijawab bagaimana melakukan ini secara terprogram. Kode ini benar-benar berfungsi, ketika ditempatkan dalam Pelanggan Pengecualian:

/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
sumber
4
Ini berfungsi dan mungkin jawaban terbaik sampai modul yang relevan (termasuk Aturan) memiliki rilis stabil. Saya harus menambahkan -> toString () ke $ query ['destination'] = Url :: fromRoute ('<current>') untuk membuatnya berfungsi
Colin Shipton
2
Jawaban ini layak untuk ditampilkan lebih tinggi!
pbonnefoi
13

Cara termudah adalah dengan browse ke /admin/config/system/site-informationdan mengisi di bidang yang berbunyi Default 403 (access denied) pagedenganuser/login

Kartagis
sumber
7
Itu adalah solusi yang baik tetapi tidak memperhitungkan fakta bahwa pengguna mungkin sudah masuk yang saya sebutkan dalam deskripsi.
9

Hanya dengan melihat judul pertanyaan ini (= Bagaimana cara mengarahkan pengguna ke formulir login dari 403? ), Ada 2 opsi untuk melakukannya, tanpa melibatkan kode kustom, seperti dirinci di bawah ini.

Opsi 1: Gunakan modul CustomError

The CustomError modul memungkinkan admin situs untuk membuat halaman kesalahan kustom untuk kode status HTTP 403 (akses ditolak) dan 404 (tidak ditemukan), tanpa menciptakan node untuk masing-masing. Beberapa detail lebih lanjut tentang fitur-fiturnya (dari halaman proyeknya):

  • Judul dan deskripsi halaman yang dapat dikonfigurasi.
  • Tidak ada header penulis dan tanggal / waktu seperti dengan node normal.
  • Teks berformat HTML apa pun dapat diletakkan di badan laman.
  • Halaman-halaman kesalahan bisa bertema.
  • Pengguna yang tidak masuk dan mencoba mengakses area yang memerlukan login akan diarahkan ke halaman yang mereka coba akses setelah mereka login.
  • Mengizinkan pengalihan khusus untuk 404s.

Anda mungkin akan lebih tertarik pada bagian tentang " Pengguna yang tidak masuk dan mencoba mengakses area yang memerlukan login akan diarahkan ke halaman yang mereka coba akses setelah mereka login. ".

Untuk D8 ada juga versi 8.x-1.x-dev untuk modul ini yang tersedia juga, perincian lebih lanjut tentang hal ini dapat ditemukan di Edisi # 2219227 .

Opsi 2: Gunakan modul Aturan

Asumsikan jalur halaman "Default 403" diatur ke no_access(via admin). Kemudian buat aturan menggunakan modul Aturan , dengan sebagai Peristiwa sesuatu seperti "Setelah mengunjungi simpul no_access". Sehingga seluruh aturan akan terlihat seperti ini:

  • Acara: Setelah mengunjungi simpulno_access
  • Kondisi:

    1. Pengguna memiliki peran -Parameter: User: [site:current-user], Roles: anonymous user
    2. BUKAN perbandingan teks -Parameter: Text: [site:current-page:url], Matching text: user/login
  • Tindakan: Pengalihan halaman -Parameter: URL: user/login

Jika Anda ingin melakukannya, Anda bahkan dapat menambahkan Tindakan lain untuk juga menampilkan beberapa pesan (informasi) di area pesan Drupal, dengan sesuatu seperti "Anda mencoba mengunjungi halaman yang memerlukan login ...".

Benar, itu mungkin mengharuskan Anda untuk mengaktifkan modul kontribusi tambahan ( Aturan ). Tetapi, seperti yang ditunjukkan oleh popularitasnya yang meningkat, modul itu mungkin sudah diaktifkan di sebagian besar situs mana pun (mirip dengan modul Views ), karena ada lusinan kasus penggunaan untuk modul ini.

Untuk D8 ada versi 8.x-3.x-alfa1 untuk modul ini juga tersedia, rincian lebih lanjut tentang versi D8 dapat ditemukan di Edisi # 2574691 , yang mencakup tautan ke masalah Peraturan " Aturan 8.x Roadmap "

Jika hal di atas tidak membantu, maka Anda mungkin ingin memeriksa apakah alasan untuk loop Anda (atau "beberapa prioritas tinggi" seperti dalam pertanyaan Anda) tidak dapat dicegah / dijelaskan dengan sesuatu yang mirip dengan jawaban pertanyaan " Cara menentukan acara Aturan seperti "Konten akan 'dilihat"? ".

Pierre
sumber
4

Saya kira solusi untuk masalah Anda sederhana. Anda dapat dengan mudah membuat halaman kustom untuk 404dan 403kemudian di dalam halaman ini, mengarahkan pengguna anonim ke /userhalaman.

Anda dapat menggunakan kode ini

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

Setiap kali 404 terjadi, Anda page--404.tpl.phpakan digunakan. Di halaman ini gunakan kode ini

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

Halaman Cara membuat halaman 403 dan 404 kustom di Drupal menjelaskan metode lain untuk membuat halaman untuk 403dan 404.

M ama D
sumber
5
Hai teman, Anda harus memeriksa tag dan kode. Orang ini jelas menggunakan Drupal 8.
alexej_d
1
hai, saya memberinya algoritma, ia dapat dengan mudah mengubahnya ke 8format
M ama D
3

Cara termudah untuk melakukannya adalah dengan menggunakan modul Redirect 403 ke User Login (versi dev itu ada untuk D8). Berikut adalah kutipan tentang hal itu (dari halaman proyeknya):

Redirect halaman kesalahan HTTP 403 ke halaman Drupal / pengguna / login dengan pesan opsional yang berbunyi:

"Akses ditolak! Anda harus masuk untuk melihat halaman ini."

Juga, halaman yang diinginkan ditambahkan dalam string kueri url sehingga, setelah login berhasil, pengguna langsung dibawa ke tempat semula mereka mencoba untuk pergi.

Marco.b
sumber
1
Mengapa jawaban ini tidak dipilih?
Miloš Kroulík
@ milos.kroulik saya kira karena pertanyaannya adalah tentang Drupal 8 tetapi modul itu untuk 7dan6
M ama D
1
Tidak ada modul yang memiliki versi Drupal 8 dalam pengembangan
Colin Shipton
1
Cukup yakin downvote itu karena jawabannya adalah jawaban "hanya tautan" (alasan khas untuk jawaban yang downvot, atau bahkan dihapus ...). Jawaban semacam itu biasanya juga muncul dalam antrian ulasan "jawaban rendah quaitas" ... Lihat versi yang diedit dari jawaban ini sekarang untuk verifikasi yang ditingkatkan untuk itu (tidak lagi berisiko dianggap sebagai jawaban hanya tautan).
Pierre.Vriens
Jawaban ini tidak memperhitungkan jika pengguna sudah login atau jika situs menggunakan fast404 dan 403.
0

(1) buat simpul halaman dengan alias seperti "/my403.html"

(2) buka / admin / config / system / informasi-situs dan set "/my403.html" sebagai 403-Errorpage

(3) buka / admin / structure / block dan tambahkan blok "User login" (Formulir Sec.) Ke wilayah konten utama. Batasi tampilan blokir ke halaman "my403.html" dan peran "tamu".

Itu dia.

Jika Anda membutuhkan lebih banyak kontrol, buat pengontrol untuk halaman 403 Anda dan tambahkan UserLoginForm dengan tangan.

Salam, Rainer

Rainer Feike
sumber