cas-8.x-1.x-dev/src/Subscriber/CasForcedAuthSubscriber.php

src/Subscriber/CasForcedAuthSubscriber.php
<?php

declare(strict_types=1);

namespace Drupal\cas\Subscriber;

use Drupal\Core\EventSubscriber\HttpExceptionSubscriberBase;
use Drupal\Core\Executable\ExecutableInterface;
use Drupal\Core\Executable\ExecutableManagerInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\cas\CasRedirectData;
use Drupal\cas\Service\CasHelper;
use Drupal\cas\Service\CasRedirector;
use Psr\Log\LogLevel;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;

/**
 * Event subscriber for implementing CAS forced authentication.
 */
class CasForcedAuthSubscriber extends HttpExceptionSubscriberBase {

  /**
   * Is forced login configuration setting enabled.
   */
  protected bool $forcedLoginEnabled = FALSE;

  /**
   * Paths to check for forced login.
   */
  protected array $forcedLoginPaths = [];

  public function __construct(
    protected readonly RouteMatchInterface $routeMatcher,
    protected readonly AccountInterface $currentUser,
    protected readonly ExecutableManagerInterface $conditionManager,
    protected readonly CasHelper $casHelper,
    protected readonly CasRedirector $casRedirector,
  ) {
    $this->forcedLoginPaths = $casHelper->getCasSetting('forced_login.paths');
    $this->forcedLoginEnabled = $casHelper->getCasSetting('forced_login.enabled');
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents(): array {
    // Run before DynamicPageCacheSubscriber (27) and
    // CasGatewayAuthSubscriber (28)
    // but after important services like RouterListener (32) and
    // MaintenanceModeSubscriber (30)
    $events[KernelEvents::REQUEST][] = ['onRequest', 29];

    $events[KernelEvents::EXCEPTION][] = ['onException', 0];
    return $events;
  }

  /**
   * Respond to kernel request set forced auth redirect response.
   *
   * @param \Symfony\Component\HttpKernel\Event\RequestEvent $event
   *   The event.
   */
  public function onRequest(RequestEvent $event): void {
    // Don't do anything if this is a sub request and not a master request.
    if ($event->getRequestType() != HttpKernelInterface::MAIN_REQUEST) {
      return;
    }

    // Some routes we don't want to run on.
    $current_route = $this->routeMatcher->getRouteName();
    if (in_array($current_route, CasHelper::IGNORABLE_AUTO_LOGIN_ROUTES)) {
      return;
    }

    // Only care about anonymous users.
    if ($this->currentUser->isAuthenticated()) {
      return;
    }

    if (!$this->forcedLoginEnabled) {
      return;
    }

    // Check if user provided specific paths to force/not force a login.
    $condition = $this->conditionManager->createInstance('request_path', $this->forcedLoginPaths);
    assert($condition instanceof ExecutableInterface);
    if (!$this->conditionManager->execute($condition)) {
      return;
    }

    $this->casHelper->log(LogLevel::DEBUG, 'Initializing forced login auth from CasSubscriber.');

    // Start constructing the URL redirect to CAS for forced auth.
    // Add the current path to the service URL as the 'destination' param,
    // so that when the ServiceController eventually processes the login,
    // it knows to return the user back here.
    $request = $event->getRequest();
    $currentPath = str_replace($request->getSchemeAndHttpHost(), '', $request->getUri());
    $redirectData = new CasRedirectData(['destination' => $currentPath]);

    $response = $this->casRedirector->buildRedirectResponse($redirectData);
    if ($response) {
      $event->setResponse($response);
      // If there's a 'destination' parameter set on the current request,
      // remove it, otherwise Drupal's RedirectResponseSubscriber will send
      // users to that location instead of to our CAS server.
      $request->query->remove('destination');
    }
  }

  /**
   * {@inheritdoc}
   */
  protected function getHandledFormats(): array {
    return ['html'];
  }

  /**
   * Handle 403 errors.
   *
   * Other request subscribers with a higher priority may intercept the request
   * and return a 403 before our request subscriber can handle it. In those
   * instances we handle the forced login redirect if applicable here instead,
   * using an exception subscriber.
   *
   * @param \Symfony\Component\HttpKernel\Event\ExceptionEvent $event
   *   The event to process.
   */
  public function on403(ExceptionEvent $event): void {
    $this->onRequest($event);
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc