Table of Contents
Description:
In this tutorial I am going to give you complete understanding of using middleware in laravel application.
By the end of this tutorial you will have a good sense of creating, configuring and applying custom middleware in laravel app, it will help you to protect or filter http request or routes.
You can follow this tutorial for your existing or brand new laravel 5 application and more specifically this tutorial supports across all laravel framework 5.+ versions.
If you are ready then let’s gets started:
What is Middleware in Laravel Application?
As name suggest middleware basically centre point between our laravel application and HTTP requests
In Laravel Framework Middleware is use to filter HTTP request while it is entering into our laravel application
There are many example of using middleware, for example detecting a user is login or not if use it not authenticated then redirect it to logging page.
If you look at the /app/Http/Middleware directory of your laravel application you will see that laravel already comes with the bunch of default configured middleware out of the box.
/app/Http/Middleware:
This middlewares are used for different operations, like if you see the first middleware we have here is Authenticate and yes it is used as our application authentication check point for the user.
Similarly there are other default middlewares like CheckForMaintenanceMode, EncryptCookies, RedirectIfAuthenticated, TrimStrings, TrustProxies and VerifyCsrfToken.
And one important note keep here is that all of this middlewares are needs to register into the application before using it and Kernel.php actually the one where we register all middlewares, if you Kernel.php file you will see that all the default middleware are by default registered into the Kernel.php file so you don’t have to worry about it.
So now in the next step I will show you can add your own custom middleware into your laravel application.
Example of creating Custom Middleware in Laravel Application
As you reading this tutorial so I assume that you already working with existing laravel application and want to create your own custom middleware to filter your http requested according to your needs.
So here in this example I going to give you step on adding route middleware, so to take an example we will basically create custom middleware for admin, so the job of our middleware will be to verify that the current authenticated user is admin or not.
So based on the role of authenticated we will protected our applications routes.
let’s get started:
Generate Laravel Middleware File:
We can generate middleware file using following php artisan command, so open up your terminal or command prompt if you are on windows and navigate to your application directory and execute following command:
php artisan make:middleware VerifyIfAdmin
The above command will generate new laravel middleware class in .php file called VerifyIfAdmin.php
Here is default definition of laravel middleware class:
<?php
namespace App\Http\Middleware;
use Closure;
class VerifyIfAdmin
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
return $next($request);
}
}
Configure middleware Action:
Next we have to configure middleware to define action, action means basically a logic or a validation rule for the http request to filter.
In this case our validation rule is to check whether the current active user is admin or normal user.
Let’s implement logic to validate the same rule, use following script:
<?php
namespace App\Http\Middleware;
use Closure;
class VerifyIfAdmin
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (!$request->user()->admin) {
if ($request->wantsJson()) {
return response()->json(['Message', 'You do not access to this module.'], 403);
}
abort(403, 'You do not access to this module.');
}
return $next($request);
}
}
If you see that in the above script in handle() function I am using $request object and from the request object I am suing the user() function to the current authenticated user and depending on the admin flag I am using the conditional statement if the user is not admin then abort the request and show 403 permission denied status code.
Note: In your application your might be having a separate table or different filed name for user role so make sure to adjust the filed name accordingly.
So here is how our middleware is going to execute:
- Check if the user is admin
- if yes proceed the request
- if not then check if request needs json response
- if yes then return json response with 403 status code
- if not then return normal repose with 403 status code
Register Custom Middleware:
As we know to execute or use any middleware into the laravel application will have to register into the Kernel.php file located inside /app/Http/ folder (/app/Http/Kernel.php)
So go ahed and open /app/Http/Kernel.php file into your code editor and register this middleware inside $routeMiddleware section as showing below:
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array
*/
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'verify.admin' => \App\Http\Middleware\VerifyIfAdmin::class,
];
Why into route middleware because the middleware we are going to use is only for specific define routes those we are going to protect this is not a global middleware because global middleware meant to be execute on each and every request coming into the application.
So now our middleware is ready to use in next let’s see how we can use middleware with laravel routes
Apply custom route middleware
So basically the goal is to add restrictions to the particular routes where only admin user should have access to it.
To demonstrate I am going to add few sample routes here as I am working on completely brand new application, in your case you might be working on your existing project so don’t worry about adding this sample routes you can directly add this middleware into your existing routes.
I will create a Admin route with an Admin Controller associated with it.
php artisan make:controller Admin/AdminController
Inside admin route I have added index method to return hello world in form of http response and it is in json format
/app/Http/Controllers/Admin/AdminController.php:
<?php
namespace App\Http\Controllers\Admin;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class AdminController extends Controller
{
public function index()
{
return response()->json(['Hello World!'], 200);
}
}
Apply Custom middleware to the route or Controller:
Apply custom middleware to route:
Next I will create a admin route with middleware applied:
/routes/web.php:
Route::get('admin/test', 'Admin\AdminController@index')->middleware(['auth', 'verify.admin']);
As you can see in the above route we have applied two middleware function and provided middleware names into the array.
So what is going to happen here first to access this route user needs to be authenticated and then next user must have an admin role.
Applying middleware to the group of routes:
Here is the example of how you can protected multiple routes using route group:
Route::group(['middleware' => ['auth', 'verify.admin']], function(){
Route::get('admin/test', 'Admin\AdminController@index');
Route::get('admin/test2', 'Admin\AdminController@test2');
Route::get('admin/test3', 'Admin\AdminController@test3');
Route::get('admin/test4', 'Admin\AdminController@test4');
});
Alternative way of protecting route using middleware:
There also an alternative way or I would say a best of way of protecting http request is to apply middleware in side our controller constructor method
Applying middleware using constructor method:
/app/Http/Controllers/Admin/AdminController.php:
<?php
namespace App\Http\Controllers\Admin;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class AdminController extends Controller
{
public function __construct()
{
$this->middleware(['auth', 'verify.admin']);
}
public function index()
{
return response()->json(['Hello World!'], 200);
}
}
So note that I have added a constructor to this Admin Controller class and simply calling an middleware function similarly as I did with the route in web.php file.
By using above way your controller will be fully protected with the middleware so all the upcoming methods you are going to add inside this AdminController will also going to get protected.
Excluding controller function from middleware:
Sometime you may want to exclude a particular function from the middleware protection so in that case it’s really you just needs to pass and except method along with the method name from the class
Here is how you can exclude a function from middleware protection:
/app/Http/Controllers/Admin/AdminController.php:
<?php
namespace App\Http\Controllers\Admin;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class AdminController extends Controller
{
public function __construct()
{
$this->middleware(['auth', 'verify.admin'])->except('testFunc');
}
public function index()
{
return response()->json(['Hello World!'], 200);
}
public function testFunc()
{
return response()->json(['Public data'], 200);
}
}
If you want to exclude multiple functions then simply pass array as a argument to the except method:
For Example:
$this->middleware(['auth', 'verify.admin'])->except(['testFunc', 'secondfunction2']);
It is always good to use controller level protection for your http request as it provides a solution to exclude particular request, but yes it is the rule you can always use the way you want it to be.
Test Custom Middleware:
Now let’s see whatever we have done so fare is working or not
Generate Laravel default auth scaffolding:
For this example I am going to generate laravel default auth scaffolding for the demonstration, of course you don’t need to do that if you working on your existing project, but yes if you are following me along with the brand new project then you can generate there is no harm to do that:
php artisan make:auth
Add custom Admin Flag into users table:
I am gone quickly add new admin filed inside users table migration before migrating it so that will have admin flag field into our table.
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->boolean('admin')->default(false);
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
Configure database settings:
Next make sure you database settings are configured in env file:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=middleware-demo
DB_USERNAME=root
DB_PASSWORD=
Migrate the database:
Next migrate the database:
php artisan migrate
Register new user:
Now I am going to register new user user, so open your project and navigate to register page:
Let’s test our admin route without admin user, because I know default new user is not an admin user it is a normal user with admin set to 0:
Test admin route with normal user:
Next let’s navigate to the admin route from the new browser tab and make sure you user is active I mean authenticated into the application:
As you can see we are getting 403 message, meaning permission denied, similarly if your going to access this endpoint with XHR request are are going to get json response with 403 status code:
Now let’s make our user to admin and try to access the route:
Test Admin with admin user:
Now access the admin route as being a admin user:
Now this time you will see that we have got our intended result.
Conclusion:
As you have seen how we can create, define and configure custom middleware in laravel and how we can utilize it for the best way possible.
There are lot of example of or needs to custom middleware so just keep in mind that whenever you want to protect or filter http request in laravel application always use laravel middleware.
there is not limit on creating middleware you can create as many as you want until you accomplish your goal of application requirement.
I hope this tutorial helps you to understand details concept of using custom middleware in laravel, if you have any question regarding laravel middleware you can let me know using comment section below and don’t forgot to like and share this tutorial to spread across the laravel developer community.
Yogesh, fantastic job on this article! Happy Diwali!