persistent_login-8.x-1.3/src/EventSubscriber/TokenHandler.php

src/EventSubscriber/TokenHandler.php
<?php

namespace Drupal\persistent_login\EventSubscriber;

use Drupal\Component\Plugin\Exception\PluginException;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Session\SessionConfigurationInterface;
use Drupal\persistent_login\CookieHelperInterface;
use Drupal\persistent_login\PersistentToken;
use Drupal\persistent_login\RawPersistentToken;
use Drupal\persistent_login\TokenException;
use Drupal\persistent_login\TokenManager;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;

/**
 * Event Subscriber to handle loading and setting tokens.
 *
 * @package Drupal\persistent_login
 */
class TokenHandler implements EventSubscriberInterface {

  /**
   * The token manager service.
   *
   * @var \Drupal\persistent_login\TokenManager
   */
  protected $tokenManager;

  /**
   * The cookie helper service.
   *
   * @var \Drupal\persistent_login\CookieHelper
   */
  protected $cookieHelper;

  /**
   * The session configuration.
   *
   * @var \Drupal\Core\Session\SessionConfigurationInterface
   */
  protected $sessionConfiguration;

  /**
   * The Entity Type Manager service.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The Config Factory service.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

  /**
   * The Current User.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $currentUser;

  /**
   * The persistent token of the current request.
   *
   * @var \Drupal\persistent_login\RawPersistentToken|null
   */
  protected $token;

  /**
   * Construct a token manager object.
   *
   * @param \Drupal\persistent_login\TokenManager $token_manager
   *   The token manager service.
   * @param \Drupal\persistent_login\CookieHelperInterface $cookie_helper
   *   The cookie helper service.
   * @param \Drupal\Core\Session\SessionConfigurationInterface $session_configuration
   *   The session configuration.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity manager service.
   * @param \Drupal\Core\Config\ConfigFactoryInterface|null $config_factory
   *   The Config Factory service.
   * @param \Drupal\Core\Session\AccountInterface|null $current_user
   *   The Current User.
   */
  public function __construct(
    TokenManager $token_manager,
    CookieHelperInterface $cookie_helper,
    SessionConfigurationInterface $session_configuration,
    EntityTypeManagerInterface $entity_type_manager,
    ConfigFactoryInterface $config_factory = NULL,
    $current_user = NULL
  ) {
    $this->tokenManager = $token_manager;
    $this->cookieHelper = $cookie_helper;
    $this->sessionConfiguration = $session_configuration;
    $this->entityTypeManager = $entity_type_manager;

    if (empty($config_factory)) {
      @trigger_error('config_factory will be a required parameter in persistent_login 2.x', E_USER_DEPRECATED);
      $config_factory = \Drupal::service('config.factory');
    }
    $this->configFactory = $config_factory;

    if (empty($current_user) || !($current_user instanceof AccountInterface)) {
      $current_user = \Drupal::currentUser();
    }
    $this->currentUser = $current_user;
  }

  /**
   * Specify subscribed events.
   *
   * @return array
   *   The subscribed events.
   */
  public static function getSubscribedEvents() {
    $events = [];

    // Must occur after AuthenticationSubscriber.
    $events[KernelEvents::REQUEST][] = ['loadTokenOnRequestEvent', 299];
    $events[KernelEvents::RESPONSE][] = ['setTokenOnResponseEvent'];

    return $events;
  }

  /**
   * Load a token on this request, if a persistent cookie is provided.
   *
   * @param \Symfony\Component\HttpKernel\Event\RequestEvent $event
   *   The request event.
   */
  public function loadTokenOnRequestEvent(RequestEvent $event) {

    if (!$event->isMainRequest()) {
      return;
    }

    $request = $event->getRequest();

    if ($this->cookieHelper->hasCookie($request)) {
      $this->token = $this->getTokenFromCookie($request);

      // Only validate the token if a user session has not been started.
      if (!empty($this->token) && $this->currentUser->isAnonymous()) {
        $this->token = $this->tokenManager->validateToken($this->token);

        if ($this->token->getStatus() === PersistentToken::STATUS_VALID) {
          try {
            /** @var \Drupal\User\UserInterface $user */
            $user = $this->entityTypeManager->getStorage('user')
              ->load($this->token->getUid());

            if (!$user || $user->isBlocked()) {
              $this->token = $this->token->setInvalid();
              return;
            }

            // @todo make sure we are starting the user session properly.
            user_login_finalize($user);
          }
          catch (PluginException $e) {
          }
        }
      }
    }
  }

  /**
   * Set or clear a token cookie on this response, if required.
   *
   * @param \Symfony\Component\HttpKernel\Event\ResponseEvent $event
   *   The response event.
   */
  public function setTokenOnResponseEvent(ResponseEvent $event) {

    if (!$event->isMainRequest()) {
      return;
    }

    if ($this->token) {
      $request = $event->getRequest();
      $response = $event->getResponse();
      $sessionOptions = $this->sessionConfiguration->getOptions($request);

      // New or updated token.
      if ($this->token->getStatus() === PersistentToken::STATUS_VALID) {
        $config = $this->configFactory->get('persistent_login.settings');
        if ($config->get('extend_lifetime') && $config->get('lifetime') > 0) {
          $this->token = $this->token->setExpiry(new \DateTime("now +" . $config->get('lifetime') . " day"));
        }

        $this->token = $this->tokenManager->updateToken($this->token);

        $response->headers->setCookie(
          Cookie::create(
            $this->cookieHelper->getCookieName($request),
            $this->token,
            $this->token->getExpiry(),
            '/', // @todo Path should probably match the base path.
            $sessionOptions['cookie_domain'],
            $sessionOptions['cookie_secure']
          )
        );
        $response->setPrivate();
      }
      elseif ($this->token->getStatus() === PersistentToken::STATUS_INVALID) {
        // Invalid token, or manually cleared token (e.g. user logged out).
        $this->tokenManager->deleteToken($this->token);
        $response->headers->clearCookie(
          $this->cookieHelper->getCookieName($request),
          '/', // @todo Path should probably match the base path.
          $sessionOptions['cookie_domain'],
          $sessionOptions['cookie_secure']
        );
        $response->setPrivate();
      }
      else {
        // Ignore token if status is STATUS_NOT_VALIDATED.
      }
    }
  }

  /**
   * Create a token object from the cookie provided in the request.
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   A request that contains a persistent login cookie.
   *
   * @return \Drupal\persistent_login\PersistentToken|null
   *   A new PersistentToken object, or NULL if the cookie value was not valid.
   */
  public function getTokenFromCookie(Request $request) {
    $cookieValue = $this->cookieHelper->getCookieValue($request);
    // Token values are 43-character base-64 encoded, URL-safe strings.
    // @see \Drupal\Component\Utility\Crypt::hmacBase64()
    if (empty($cookieValue) || !preg_match('<[a-z0-9_-]+:[a-z0-9+_-]+>i', $cookieValue)) {
      return NULL;
    }
    return RawPersistentToken::createFromString($cookieValue);
  }

  /**
   * Create and store a new token for the specified user.
   *
   * @param int $uid
   *   The user id to associate the token to.
   */
  public function setNewSessionToken($uid) {
    try {
      $this->token = $this->tokenManager->createNewTokenForUser($uid);
    }
    catch (TokenException $e) {
      // Ignore error creating new token.
    }
  }

  /**
   * Mark the user's current token as invalid.
   *
   * This will cause the token to be removed from the database at the end of the
   * request.
   */
  public function clearSessionToken() {
    if ($this->token) {
      $this->token = $this->token->setInvalid();
    }
  }

}

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

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