I want if user not logged in and visit any page of my website except my REST VIEWS routers I redirect him/her to login page in drupal 8, I found this solutions for drupal 7 but didn't find any solution for Drupal 8,
4 Answers
You can test a user's status very early with event subscriber in a custom module that subscribes to KernelEvents::REQUEST.
First, you register the event subscriber in mymodule.services.yml
in your module folder:
services:
mymodule.event_subscriber:
class: Drupal\mymodule\EventSubscriber\RedirectAnonymousSubscriber
arguments: []
tags:
- {name: event_subscriber}
Then add RedirectAnonymousSubscriber.php
for your custom event subscriber in your module in the /src/EventSubscriber/
folder.
namespace Drupal\mymodule\EventSubscriber;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Event subscriber subscribing to KernelEvents::REQUEST.
*/
class RedirectAnonymousSubscriber implements EventSubscriberInterface {
public function __construct() {
$this->account = \Drupal::currentUser();
}
public function checkAuthStatus(GetResponseEvent $event) {
if ($this->account->isAnonymous() && \Drupal::routeMatch()->getRouteName() != 'user.login') {
// add logic to check other routes you want available to anonymous users,
// otherwise, redirect to login page.
$route_name = \Drupal::routeMatch()->getRouteName();
if (strpos($route_name, 'view') === 0 && strpos($route_name, 'rest_') !== FALSE) {
return;
}
$response = new RedirectResponse('/user/login', 301);
$event->setResponse($response);
$event->stopPropagation();
}
}
public static function getSubscribedEvents() {
$events[KernelEvents::REQUEST][] = array('checkAuthStatus');
return $events;
}
}
-
-
1he should create
RedirectAnonymousSubscriber.php
,I update your answer.– YuseferiDec 16, 2016 at 8:28 -
@oknate what if user is on /registration or /forget-password or /logout route ? Shouldn't it check for those routes as well in the if condition ? As as per this, the user might be redirect while registering or request for the new password. Jul 17, 2019 at 6:48
-
2Another important detail here is "priority" of the subscriber. I found some routes will resolve before the redirect above kicks in. But setting the priority (a higher number fires first) helps to resolve that. In the example above, use array('checkAuthStatus', 100). Docs on subscriber and priority: symfony.com/doc/current/event_dispatcher.html– BWagnerFeb 7, 2020 at 1:39
-
1Thanks oknate for this snippet. I've had to tweak it a bit to also allow other user paths like password reset etc. stefvanlooveren.me/blog/… Feb 10, 2021 at 10:30
First, create a service for your event subscriber in module-name.services.yml
Code -
services:
[MODULE-NAME]_event_subscriber:
class: Drupal\MODULE-NAME\EventSubscriber\[Event-Subscriber-class]
tags:
- {name: event_subscriber}
Create your own eventsubscriber class inside modules/module-name/src/EventSubscriber
directory:
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
class Event-Subscriber-class implements EventSubscriberInterface {
private $redirectCode = 301;
public function checkForRedirection2(GetResponseEvent $event) {
$account = \Drupal::currentUser();
if (empty($account->id()) {
$response = new RedirectResponse('/', $this->redirectCode);
$response->send();
exit(0);
}
}
public static function getSubscribedEvents() {
$events[KernelEvents::REQUEST][] = array('checkForRedirection2');
return $events;
}
}
On Drupal 8.3.3, this code causes an endless redirection. I've fixed that by adding that instead.
..
$response = new RedirectResponse('/user/login', 301);
$response->send();
..
This answer is compatible for Drupal 8, and 9.
First, you register the event subscriber in redirect_anonymous_users.services.yml
in your module folder (taken from @oknate's answer):
services:
redirect_anonymous_users.event_subscriber:
class: Drupal\redirect_anonymous_users\EventSubscriber\RedirectAnonymousSubscriber
arguments: []
tags:
- {name: event_subscriber}
Then add RedirectAnonymousSubscriber.php for your custom event subscriber in your module in the /src/EventSubscriber/
folder.
namespace Drupal\redirect_anonymous_users\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
/**
* Event subscriber subscribing to KernelEvents::REQUEST.
*/
class RedirectAnonymousSubscriber implements EventSubscriberInterface {
public function checkAuthStatus(GetResponseEvent $event) {
if (
\Drupal::currentUser()->isAnonymous() &&
\Drupal::routeMatch()->getRouteName() != 'user.login'
) {
$response = new RedirectResponse('/user/login', 302);
$response->send();
}
}
/**
* {@inheritDoc}
*/
public static function getSubscribedEvents() {
$events[KernelEvents::REQUEST][] = array('checkAuthStatus');
return $events;
}
}
-
Nice example! But it wold be better if it used Dependency Injection instead of hard-wired calls to
\Drupal::currentUser()
and\Drupal::routeMatch()
.– berlinerOct 28, 2021 at 20:57
KernelEvents::REQUEST
event and then set the response to a RedirectResponse for the login page./user
and then if they're anonymous, it would take them to/user/login
, but with the side effect of taking authenticated users to their user profile without telling them they've been denied access to the page they were looking for.