Middleware can be used to intercept and modify HTTP requests before they reach the application, allowing developers to inspect and filter the requests based on specific criteria. This can be useful for adding additional security measures, handling errors and exceptions, or modifying the request/response header.
Drupal provides a robust middleware system that allows developers to create their own middleware to modify incoming requests and outgoing responses.
In Drupal, we can define our middleware in a separate class file and then declare it as a service in a .services.yml
file. The middleware class needs to implement the HttpKernelInterface
and be tagged with http_middleware
. then the StackedKernelPass
(A compiler pass) discover and register those middlewares.
Let's proceed further and develop our custom middleware. In this middleware, we will secure our login page with a static username and password. We can make username and password dynamic but we will not cover it in this article.
Step 1: Define your middleware.
<?php
declare(strict_types=1);
namespace Drupal\starter_base\StackMiddleware;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
use Symfony\Component\HttpKernel\HttpKernelInterface;
/**
* Provides basic auth to protect our login page.
*/
class LoginProtectorMiddleware implements HttpKernelInterface {
protected const LOGIN_PATH = '/user/login';
protected const BASIC_AUTH_USER = 'authuser';
protected const BASIC_AUTH_PASS = 'authpass';
/**
* The next http middleware.
*
* @var \Symfony\Component\HttpKernel\HttpKernelInterface
*/
protected $app;
/**
* Constructor for LoginProtectorMiddleware
*
* @param \Symfony\Component\HttpKernel\HttpKernelInterface $app
* The next http middleware.
*/
public function __construct(HttpKernelInterface $app) {
$this->app = $app;
}
/**
* {@inheritdoc}
*/
public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = TRUE): Response {
if ($request->getPathInfo() != self::LOGIN_PATH) {
return $this->app->handle($request, $type, $catch);
}
$username = $request->headers->get('PHP_AUTH_USER');
$password = $request->headers->get('PHP_AUTH_PW');
if ($username === self::BASIC_AUTH_USER && $password === self::BASIC_AUTH_PASS) {
return $this->app->handle($request, $type, $catch);
}
throw new UnauthorizedHttpException(
'Basic',
'No authentication credentials provided.'
);
}
}
Step 2: Declare middleware in .services.yml
file.
services:
starter_base.login_protector_middleware:
class: Drupal\starter_base\StackMiddleware\LoginProtectorMiddleware
tags:
- { name: http_middleware, priority: 250 }
The higher the priority value, the earlier the middleware will be executed in the request/response chain.
Output: