In this post, I would like to show you very simple approach to develop a security layer around Laravel routes with custom Middleware.
Laravel Middleware
Middleware provides a convenient mechanism for filtering HTTP requests entering your application. middleware are series of “layers” where HTTP requests must pass through before they hit your application. Each layer can examine the request and even reject it entirely.
The Database
We will be using the following tables:
users: This table stores all of the user data.
roles: This table stores all of the roles lists.
For the sake of simplicity in this tutorial, one user can have only one role, so the role_id column added to the users’ table.
Generating and Running the Migrations
By default, Laravel 5 comes with a user table migration so just update it by adding role_id
column.
Now we need role migration, to create a roles table, generate a new migration by running php artisan make:migration create_roles_table
and add the following code to it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateRolesTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('roles', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->string('slug')->unique(); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('roles'); } } |
Now we have required migrations in place, to create tables run them using php artisan migrate
.
Creating and updating Models
By default, Laravel 5 comes with a User
model, so we do not have to create it. But We need to update it by adding the role method to it.
Add the following to the App\User
model.
1 2 3 4 |
public function role() { return $this->hasOne(Role::class); } |
Now we need a Role
model, to generate run the following command php artisan make:model Role
.
Add your App\Role
model might be like below shown text
1 2 3 4 5 6 7 8 9 10 |
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Role extends Model { // } |
Creating middleware
Adding a middleware to provide role based access control is just as simple. To create a new middleware, use the make:middleware
Artisan command:
1 |
php artisan make:middleware RoleGate |
Above command will place a new RoleGate
class within your app/Http/Middleware
directory. In this middleware, we will only allow access to the route if the supplied role is assigned to the user. Otherwise, we will redirect the users back to the login URI.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<?php namespace App\Http\Middleware; use Closure; class RoleGate { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next,$role) { if ($request->user() && $request->user()->role && $request->user()->role->slug === $role) { return $next($request); } return redirect('/login'); } } |
As you can see, if the given role is assigned to the currently authenticated user, the request will be passed further into the application, otherwise, the middleware will return an HTTP redirect to the login URI. To pass the request deeper into the application (allowing the middleware to “pass”), simply call the $next
callback with the $request
.
Registering Middleware
Open app/Http/Kernel.php
and add your newly RoleGate middleware to the application’s route middleware’s array as shown below –
1 2 3 4 5 6 7 8 9 |
protected $routeMiddleware = [ 'auth' => \Illuminate\Auth\Middleware\Authenticate::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class, 'can' => \Illuminate\Auth\Middleware\Authorize::class, 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'role' => \App\Http\Middleware\RoleGate::class, ]; |
How use it to protect roles
Once the middleware has been defined in the HTTP kernel, you may use the middleware method to assign middleware to a route:
1 2 3 |
Route::get('admin/profile', function () { // })->middleware('role:admin'); // allow only for role |
I hope you like this Post, Please feel free to comment below, your suggestion and problems if you face - we are here to solve your problems.