You are here

class ShieldMiddleware in Shield 8

Middleware for the shield module.

Hierarchy

  • class \Drupal\shield\ShieldMiddleware implements \Symfony\Component\HttpKernel\HttpKernelInterface

Expanded class hierarchy of ShieldMiddleware

1 string reference to 'ShieldMiddleware'
shield.services.yml in ./shield.services.yml
shield.services.yml
1 service uses ShieldMiddleware
shield.middleware in ./shield.services.yml
Drupal\shield\ShieldMiddleware

File

src/ShieldMiddleware.php, line 16

Namespace

Drupal\shield
View source
class ShieldMiddleware implements HttpKernelInterface {

  /**
   * The decorated kernel.
   *
   * @var \Symfony\Component\HttpKernel\HttpKernelInterface
   */
  protected $httpKernel;

  /**
   * The config factory.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

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

  /**
   * The path matcher.
   *
   * @var \Drupal\Core\Path\PathMatcherInterface
   */
  protected $pathMatcher;

  /**
   * Constructs a BanMiddleware object.
   *
   * @param \Symfony\Component\HttpKernel\HttpKernelInterface $http_kernel
   *   The decorated kernel.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The configuration factory.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The EntityTypeManager service.
   * @param \Drupal\Core\Path\PathMatcherInterface $path_matcher
   *   The path matcher service.
   */
  public function __construct(HttpKernelInterface $http_kernel, ConfigFactoryInterface $config_factory, EntityTypeManagerInterface $entity_type_manager, PathMatcherInterface $path_matcher) {
    $this->httpKernel = $http_kernel;
    $this->configFactory = $config_factory;
    $this->entityTypeManager = $entity_type_manager;
    $this->pathMatcher = $path_matcher;
  }

  /**
   * {@inheritdoc}
   */
  public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE) {
    $config = $this->configFactory
      ->get('shield.settings');
    $allow_cli = $config
      ->get('allow_cli');
    $user = NULL;
    switch ($config
      ->get('credential_provider')) {
      case 'shield':
        $user = $config
          ->get('credentials.shield.user');
        $pass = $config
          ->get('credentials.shield.pass');
        break;
      case 'key':
        $user = $config
          ->get('credentials.key.user');

        /** @var \Drupal\Core\Entity\EntityStorageInterface $storage */
        $storage = $this->entityTypeManager
          ->getStorage('key');

        /** @var \Drupal\key\KeyInterface $pass_key */
        $pass_key = $storage
          ->load($config
          ->get('credentials.key.pass_key'));
        if ($pass_key) {
          $pass = $pass_key
            ->getKeyValue();
        }
        break;
      case 'multikey':

        /** @var \Drupal\Core\Entity\EntityStorageInterface $storage */
        $storage = $this->entityTypeManager
          ->getStorage('key');

        /** @var \Drupal\key\KeyInterface $user_pass_key */
        $user_pass_key = $storage
          ->load($config
          ->get('credentials.multikey.user_pass_key'));
        if ($user_pass_key) {
          $values = $user_pass_key
            ->getKeyValues();
          $user = $values['username'];
          $pass = $values['password'];
        }
        break;
    }

    // Check if enabled.
    $shield_enabled = $config
      ->get('shield_enable') && !empty($user);
    if (!$shield_enabled || $type != self::MASTER_REQUEST || PHP_SAPI === 'cli' && $allow_cli) {

      // Bypass:
      // 1. Empty username or Disabled from configuration.
      // 2. Subrequests.
      // 3. CLI requests if CLI is allowed.
      return $this->httpKernel
        ->handle($request, $type, $catch);
    }
    else {

      // Check if user IP is in whitelist.
      $in_whitelist = FALSE;
      if ($whitelist = $config
        ->get('whitelist')) {
        $whitelist = array_filter(array_map('trim', explode("\n", $whitelist)));
        $in_whitelist = IpUtils::checkIp($request
          ->getClientIp(), $whitelist);
      }

      // Check if site domain is in whitelist.
      $allow_domain = FALSE;
      if ($domains = $config
        ->get('domains')) {
        if (!empty($domains)) {
          $allow_domain = $this->pathMatcher
            ->matchPath($request
            ->getHost(), $domains);
        }
      }

      // Check if user has provided credentials.
      if ($request->server
        ->has('PHP_AUTH_USER') && $request->server
        ->has('PHP_AUTH_PW')) {
        $input_user = $request->server
          ->get('PHP_AUTH_USER');
        $input_pass = $request->server
          ->get('PHP_AUTH_PW');
      }
      elseif (!empty($request->server
        ->get('HTTP_AUTHORIZATION'))) {
        list($input_user, $input_pass) = explode(':', base64_decode(substr($request->server
          ->get('HTTP_AUTHORIZATION'), 6)), 2);
      }
      elseif (!empty($request->server
        ->get('REDIRECT_HTTP_AUTHORIZATION'))) {
        list($input_user, $input_pass) = explode(':', base64_decode(substr($request->server
          ->get('REDIRECT_HTTP_AUTHORIZATION'), 6)), 2);
      }
      $authenticated = isset($input_user) && $input_user === $user && hash_equals($pass, $input_pass);
      if ($in_whitelist || $authenticated || $allow_domain) {
        return $this->httpKernel
          ->handle($request, $type, $catch);
      }
    }
    $response = new Response();
    $response->headers
      ->add([
      'WWW-Authenticate' => 'Basic realm="' . strtr($config
        ->get('print'), [
        '[user]' => $user,
        '[pass]' => $pass,
      ]) . '"',
    ]);
    $response
      ->setStatusCode(401);
    return $response;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
ShieldMiddleware::$configFactory protected property The config factory.
ShieldMiddleware::$entityTypeManager protected property The EntityTypeManager service.
ShieldMiddleware::$httpKernel protected property The decorated kernel.
ShieldMiddleware::$pathMatcher protected property The path matcher.
ShieldMiddleware::handle public function Handles a Request to convert it to a Response.
ShieldMiddleware::__construct public function Constructs a BanMiddleware object.