如何检查整个网站而不是模块/路径的“ _custom_access”?

时间:2019-08-08 10:23:01

标签: drupal-8

example:
  path: '/example'
  defaults:
    _controller: '\Drupal\example\Controller\ExampleController::content'
  requirements:
    _custom_access: '\Drupal\example\Controller\ExampleController::access'

仅当有人呼叫 mywebsite.domain / example 时,才会执行此custom_access检查器。

但是我希望该控制器检查所有url,独立于路径运行。

如何创建独立的自定义访问控制器?

1 个答案:

答案 0 :(得分:0)

防止路由访问到非常低的级别(准确地说是Kernel)的想法是注册EventSubscriber KernelEvent来注册REQUEST服务。

  1. 首先,您需要创建一个new custom module

  2. 完成后,您将可以创建一个新的my_module.services.yml文件,该文件将声明一个新的EventSubscriber

services:
  my_module.subscriber:
    class: Drupal\my_module\EventSubscriber\MyCustomSubscriber
    tags:
      - { name: event_subscriber}
  1. 然后,在my_module/src/EventSubscriber/MyCustomSubscriber.php中创建上面引用的类。 这是一个小示例,该示例在访问任何页面之前检查当前用户是否已登录,否则在登录页面上重定向。以下代码并不完整(请参阅最后一个参考以获取更好的解释),但它向您展示了基础知识(订阅事件,依赖项注入,事件重定向等)
<?php

namespace Drupal\my_module\EventSubscriber;

use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;

class MyCustomSubscriber implements EventSubscriberInterface {

  /**
   * The current route match.
   *
   * @var \Drupal\Core\Routing\RouteMatchInterface
   */
  protected $routeMatch;

  /**
   * Class constructor.
   *
   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
   *   The current route match.
   */
  public function __construct(RouteMatchInterface $route_match) {
    $this->routeMatch = $route_match;
  }

  /**
   * {@inheritdoc}
   */
  static function getSubscribedEvents() {
    $events[KernelEvents::REQUEST][] = ['isLoggedIn'];
    return $events;
  }

  /**
   * It verify the page is requested by a logged in user, otherwise prevent access.
   *
   * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
   *   A response for a request.
   */
  public function isLoggedIn(GetResponseEvent $event) {
    $route_name = $this->routeMatch->getRouteName();

    // Don't run any assertion on the login page, to prevent any loop redirect.
    // If intend to be used on a production project, please @see
    // https://www.lucius.digital/en/blog/drupal-8-development-always-redirect-all-logged-out-visitors-to-the-login-page for a better implementation.
    if ($route_name === 'user.login') {
      return;
    }

    if (\Drupal::currentUser()->isAnonymous()) {
      $dest = Url::fromRoute('user.login')->toString();
      $event->setResponse(RedirectResponse::create($dest));
    }
  }
}

要进一步讲解,您可以阅读有关注册事件订阅者的说明和一些用例:

希望它能对您有所帮助。