Middleware, Layer Filter And Extra Security in Laravel 5

HTTP Middleware is one of the best facilities Laravel 5 ships with. It not only adds extra security to your application but also gives you enough freedom to create your own security mechanism alongside the default Laravel Authentication mechanism. As you know already, when a user requests for a page, the browser sends the request and the server responds. Sometimes, this request­response mechanism is simple and sometimes it is fairly complicated. But at the end of the day whenever a user requests for a page a HTTP request enters your application. Most of the time it is innocuous but as the proverb goes you can not and should not rely on user’s input or request so it needs to filtered. It has to be filtered when your application needs extra bit of authentication or security measures to be taken. Middleware does this thing out of the box.
Laravel 5 ships with ‘Authenticate’ middleware. It is default so that you need not tweak it to add some extra security to your application. The mechanism is very simple. It verifies the user’s credentials and permits it to enter your application and proceed further. But besides this default Middleware we can add our own functionalities. We will check it very soon. But before doing that let us check the default one and see how it works. Got to the ‘app/Http/Middleware’ folder and open up the ‘Authenticate.php’ page. This part of code looks interesting.

1.
2.
3.namespace App\Http\Middleware;
4.
5.use Closure;
6.use Illuminate\Contracts\Auth\Guard;
7.
8.class Authenticate
9.{
10. /**
11. * The Guard implementation.
12. *
13. * @var Guard
14. */
15. protected $auth;
16.
17. /**
18. * Create a new filter instance.
19. *
20. * @param Guard $auth
21. * @return void
22. */
23. public function __construct(Guard $auth)
24. {
25. $this­->auth = $auth;
26. }
27.
28. /**
29. * Handle an incoming request.
30. *
31. * @param \Illuminate\Http\Request $request
32. * @param \Closure $next
33. * @return mixed
34. */
35. public function handle($request, Closure $next)
36. {
37. if ($this-­>auth-­>guest()) {
38. if ($request­->ajax()) {
39. return response('Unauthorized.', 401);
40. } else {
41. return redirect()­->guest('auth/login');
42. }
43. }
44.
45. return $next($request);
46. }
47.
}

Here the line number sixth is very important. The class uses this line:
use Illuminate\Contracts\Auth\Guard;
Next, in the construct level it instantiates this ‘auth’ so that in the handle function it can check whther the user is a guest or an authenticated user. Fairly simple task. But there is something more. In that folder, there is another file ‘RedirectIfAuthenticated.php’. Let us see its code also:

namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Auth\Guard;
class RedirectIfAuthenticated
{
/**
* The Guard implementation.
*
* @var Guard
*/
protected $auth;
/**
* Create a new filter instance.
*
* @param Guard $auth
* @return void
*/
public function __construct(Guard $auth)
{
$this­>auth = $auth;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if ($this­>auth­>check()) {
return redirect('/home');
}
return $next($request);
}
}

It does almost same thing. It is checking user’s authentication and permits it to go to the desired location. Here it is
1.if ($this­->auth-­>check()) {
2. return redirect('/home');
3. }

Now, question is, how it works out of the box? To find out our answer, we need to go to our ‘routes.php’ page. Here we have already seen how we can use the ‘log in, log out and register’ process using default authentication mechanism. Doing that we had to write a piece of code like this:

1.Route::group(['middleware' => 'auth'], function () {
2. Route::get('home', function () {
3. return view('auth.home');
4. });
5.
6. Route::get('dashboard', function () {
7. return view('auth.dashboard');
8. });
9. });

You go through the first line and hopefully it now makes sense with the default Middleware logic. In our Route Group, we used
['middleware' => 'auth']
And it distantly connects with the in built Authentication Middleware. Actually it is defined in ‘app/Kernel.php’ as a protected property like this:

1./**
2. * The application's route middleware.
3. *
4. * @var array
5. */
6. protected $routeMiddleware = [
7. 'auth' =>
\App\Http\Middleware\Authenticate::class,
8. 'auth.basic' =>
\Illuminate\Auth\Middleware\AuthenticateWithBasicAuth:
:class,
9. 'guest' =>
\App\Http\Middleware\RedirectIfAuthenticated::class,
10. ];

How the default Authenticate Middleware works is now clear­compiled. How about adding some our own functionalities? So far we have seen in our Authentication Chapter, a user logs in and she goes to the ‘/dashboard’. Well we need to add some extra functionalities in our ‘users’ table first. So that one of the users will be the administrator and only she can check into a ‘blog’ page.
Since we need to test our own Middleware at the ground lavel, we have decided to make it the simplest one. So we keep a link to that ‘Blog’ page in our ‘Dashboard’ page. Now every user logs in and clicks that link. But our Middleware will check whether that user is administrator or not. If she is an administrator, she can land up to the ‘Blog’ page with special Administrative power and if she is not that, she will sent back to the home page for general users. This is our simple administrator Middleware building procedural step. Let us start.
First, we need to set up one extra column in our ‘users’ table­cell. We need to migrate for that. You can do it manually in your PHPMyAdmin or directly use Tinker to add that column. But migration is simpler.
Open up the terminal and go to our laravel application and issue this command:
php artisan make:migration add_is_admin_to_user_table –table=users
Go to the ‘database’ folder and see that your new migration has been created. Now before migrating starts we need to tweak the up() and down() method like this:

2.
3.use Illuminate\Database\Schema\Blueprint;
4.use Illuminate\Database\Migrations\Migration;
5.
6.class AddIsAdminToUserTable extends Migration
7.{
8. /**
9. * Run the migrations.
10. *
11. * @return void
12. */
13. public function up()
14. {
15. Schema::table('users', function (Blueprint $table) {
16. $table­->boolean('is_admin')­->default(false);
17. });
18. }
19.
20. /**
21. * Reverse the migrations.
22. *
23. * @return void
24. */
25. public function down()
26. {
27. Schema::table('users', function (Blueprint
$table) {
28. $table­->dropColumn('is_admin');
29. });
30. }
31.
}

Now we are ready to migrate, so issue this command:
php artisan migrate
Check your ‘users’ table and see there is one extra column has already been added and each one is false. So you choose any one user and make her the administrator so that when we check the authentication it comes out true. Our database set up is ready. Now we can proceed for the next step. This step involves creating our own Middleware logic which will check whether the user is administrator or not. If she is the administrator, she can go the ‘Blog’ page. Otherwise she will sent back to the Home page for general users. We can create our custom Middleware through the console. In our terminal, we issue this command:
php artisan make:middleware RoleMiddleware
As you see, we name our Middleware ‘RoleMiddleware’. You can name it differently. No problem. It will immediately shots back with a prompt that says, your middleware has been successfully created. Let us go to the ‘app/Http/Middleware’ folder and check it. Yes, it has been created. It comes up with a handle() method as usual. Now all we need, is to add this line of code on top of the page first:
use Illuminate\Contracts\Auth\Guard;
Because we need to check the user’s authenticity.
The full code looks like this:

2.
3.namespace App\Http\Middleware;
4.use Closure;
5.use Illuminate\Contracts\Auth\Guard;
6.use Illuminate\Http\RedirectResponse;
7.//use App\User;
8.
9.class RoleMiddleware
10.
{
11. protected $auth;
12.

13. public function __construct(Guard $auth) {
14. $this­->auth = $auth;
15. }
16.
17.
18. /**
19. * Handle an incoming request.
20. *
21. * @param \Illuminate\Http\Request $request
22. * @param \Closure $next
23. * @return mixed
24. */
25. public function handle($request, Closure $next)
26. {
27. if ($this-­>auth-­>check())
28. {
29. if ($this­>auth­>user()-­>is_admin == TRUE)
30. {
31. return $next($request);
32. }
33. }
34.

35. return new
RedirectResponse(url('/auth/login'));
36. }
37.
38. }

Line 27 and line 29 are very important and you take the note that it ultimately plays the crucial part in our own Middleware.
The logic is fairly simple. Our ‘RoleMiddleware’ class whenever is called up an instance of ‘Guard’ is created and that will take care of further authentication process. So in our handle() method that passes two parameters ‘request’ and ‘Closure $next’, we will add some extra spices so that when it is checked the credentials of the user, it looks up and asks is she administrator? If not it sends her back to the log in page. So if someone just type the URL and try to enter into our ‘Blog’ page she will be sent back to the log in page. Now if she is a registered user she can log in but ends up at the ‘Dashboard’ page. To facilitate this ‘RoleMiddleware’ we need to add an extra Route Group in our ‘routes.php’ file like this:

1.Route::group(['middleware' => 'auth'], function () {
2. Route::get('home', function () {
3. return view('auth.home');
4. });
5.
6. Route::get('dashboard', function () {
7. return view('auth.dashboard');
8. });
9. });
10.
Route::group(['middleware' => 'role'], function ()
{
11.

12. Route::get('blog', function () {
13. return view('blog.index');
14. });
15.

16. });

You see at line number 10, we add an extra Route Group Middleware, ‘role’. But question is how our application will learn about it? Okay, our step is incomplete till now. We need to register it to ‘app/Kernel’ so the ‘app/Kernel.php’ code looks like this:

1.protected $routeMiddleware = [
2. 'auth' => \App\Http\Middleware\Authenticate::class,
3. 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth:
:class,
4. 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
5. 'iplog' => \App\Http\Middleware\RequestLogger::class,
6. 'role' => \App\Http\Middleware\RoleMiddleware::class,
7. ];

Watch out for the line number 6. We have registered our
'role' => \App\Http\Middleware\RoleMiddleware::class,
And it will now work like a breeze. The next steps are left to create one Controller and View page. That you can do. In the next chapter we will officially launch a administrator facility and will create a Administrative dashboard where an administrator can create, edit and delete users.
So far you have seen how we can control access to the users by using various types of Middleware. Use your imagination to build up all the crazy Middleware and the procedure is not very complex enough. You can handle it by yourself. Suppose, we want to check users point earned in a forum. We can do some more weird staff like checking whether a user’s name consists of any particular alphabet etcetera. We can use ‘before’ and ‘after’ Middleware so that our application will handle something beforehand and execute something after.
Suppose, we want to check the forum points of a user. We can create a Middleware like this:

1.namespace App\Http\Middleware;
2.
3. use Closure;
4.
5. class PointMiddleware
6. {
7. /**
8. * Run the request filter.
9. *
10. * @param
\Illuminate\Http\Request $request
11. * @param \Closure $next
12. * @return mixed
13. */
14. public function handle($request, Closure $next)
15. {
16. if ($request­->input('point') <= 500) {
17. return redirect('home');
18. }
19.
20. return $next($request);
21. }
22.
23.
}

Now we can also handle this before and after like this:

1.namespace App\Http\Middleware;
2.
3. use Closure;
4.
5. class BeforeMiddleware
6. {
7. public function handle($request, Closure
$next)
8. {
9. // Perform action
10.

11. return $next($request);
12. }
13. }
14.
namespace App\Http\Middleware;
15.
16. use Closure;
17.
18. class AfterMiddleware
19. {
20. public function handle($request, Closure
$next)
21. {
22. $response = $next($request);
23.

24. // Perform action
25.
26. return $response;
27. }
28. }

So there are lot of actions waiting to explored inside this Middleware section. We will conclude with a logging Middleware that will log every request coming to your application. A very simple and elegant one. You have learned how to create a MiddleWare. So create a ‘IPLogger’ Middleware first. And add a one line of code in your handle() method like this:

1.getClientIp());
19. return $next($request);
20. }
21.
}

Next in your ‘routes.php’ add this Middleware
Group like this:

1.Route::get('/', ['middleware' => 'iplog', function ()
{
2. return view('index');
3. }]);

So that each time a user sends request to the index page, his ‘ip address’ will be stored in the ‘storage/logs/laravel.log’ like this:
1. [2015­08­22 18:16:14] local.INFO: ::ip­address
2. [2015­08­22 18:16:55] local.INFO: ::ip­address
//output is incomplete
I forgot to mention, you should have registered your ‘IPMiddleware’ in ‘app/Http/Kernel.php’ like this:
‘iplog’ => \App\Http\Middleware\IPLogger::class,
And it is done!
Please have a look into the documentation for more valuable inputs like Middleware parameters and Terminable Middleware where you start a session and stores it your storage and terminates it after your task has been accomplished.

https://leanpub.com/laravel5learneasy/embed


Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s