Laravel: Difference Between Route Middleware and Policy
Asked Answered
W

4

40

Developing an app with laravel I realised that what can be done with Policy can exactly be done with Middleware. Say I want to prevent a user from updating a route if he/she is not the owner of the information, I can easily check from the route and can do the same from the policy.

So my question is why should I use policy over middleware and vice versa

Warrick answered 26/1, 2016 at 16:50 Comment(1)
I think you should try to look at it like this: middleware is used for authenticating whereas policies are for the use of authorisation.Nirvana
P
71

I'm currently going through a small refactor with my roles, permissions and routes and asked myself the same question.

At the surface level, it appears true middleware and policies perform the same general idea. Check if a user can do what they are doing.

For reference here's the laravel docs...

Middleware "May I see this? May I go here?"

HTTP middleware provide a convenient mechanism for filtering HTTP requests entering your application. For example, Laravel includes a middleware that verifies the user of your application is authenticated. If the user is not authenticated, the middleware will redirect the user to the login screen. However, if the user is authenticated, the middleware will allow the request to proceed further into the application.

Of course, additional middleware can be written to perform a variety of tasks besides authentication. A CORS middleware might be responsible for adding the proper headers to all responses leaving your application. A logging middleware might log all incoming requests to your application.

https://laravel.com/docs/master/middleware#introduction

In my reading, Middleware is about operating at the request level. In the terms of "Can this user see a page?", or "Can this user do something here?"

If so, it goes to the controller method associated with that page. Interestingly enough, Middleware may say, "Yes you may go there, but I'll write down that you are going." Etc.

Once it's done. It has no more control or say in what the user is doing. Another way I think of it as the middleperson.

Policies "Can I do this? Can I change this?"

In addition to providing authentication services out of the box, Laravel also provides a simple way to organize authorization logic and control access to resources. There are a variety of methods and helpers to assist you in organizing your authorization logic, and we'll cover each of them in this document.

https://laravel.com/docs/master/authorization#introduction

Policies however, appear to be more concerned with doing. Can the user update any entry, or only theirs?

These questions seem fit for a controller method where all the calls to action on a resource are organized. Retrieve this object, store or update the article.

As tjbb mentioned, middleware can make routes very messy and hard to manage. This is an example from my routes file:

The problem

    Route::group(['middleware' =>'role:person_type,person_type2',], function () {
        Route::get('download-thing/{thing}', [
             'as' => 'download-thing', 
             'uses' => 'ThingController@download'
        ]);
    }); 

This gets very hard to read in my route file!

Another approach with policies

//ThingController
public function download(Thing $thing)
{
    //Policy method and controller method match, no need to name it
    $this->authorize($thing);

    //download logic here....
}
Philately answered 24/2, 2016 at 1:42 Comment(2)
What does 'as' => 'download-thing' do? I feel like it does something like 'act as this model when processing the rest of this request'. I'm trying to find documentation on it, but no luck so far. edit: I found it. It lets you 'name' a route, for ease of use when generating a URL or redirecting the user. Far less useful for me :(Starstarboard
Great answer! Another benefit of the policy is that you can use it in your blade templates with the can command.Charmaincharmaine
I
23

Route middleware allows you to apply request handling to a large range of routes, instead of repeating the code in every controller action - checking authentication and redirecting guests is a good example. Controllers instead contain logic unique to specific routes/actions - you could use middleware for this, but you'd need separate middleware for every route's logic and it would all get very messy.

Policies/abilities are simply a way of checking user permissions - you can query them from a controller, or from middleware, or anywhere else. They only return true or false, so they aren't equivalent to controllers or middleware. Most of the time abilities will be comparing a user to another model, which will have been loaded based on an identifier sent to a controller action, but there are probably some applications for use with middleware too.

Intermix answered 27/1, 2016 at 3:20 Comment(0)
E
0

I have asked myself the same question. In practice, I predominantly use middleware. My most common usage is when authorisation is only allowed for a specific user, for instance:

public function update(User $user, user $model)
{
    return $user->id === $model->id;
}

Though, even in the instance above, Yes, one could do without it and write their own logic in the controller to do the same thing.

I also like the before method, which I use to allow the administrator full-privileges for a model, for example:

public function before($user, $ability)
{
    if ($user->admin === 1) {
        return true;
    }
}

The main reason, though, why I have started to use Policies on some Laravel projects is because of what you can do with blade. If you find yourself setting permissions numerous times for the same user authorisation in your blade files, for example, to show an edit button, then Policies may become very useful because you can do the following with them (and more):

@can('update', $post)
<button class="btn btn-primary">Edit Post</button>
@endcan

@cannot('create', App\Models\Post::class)
<div class="alert alert-warning">You are not allowed to create a post</div>
@endcannot

I sometimes find these Policy-referencing blade methods to be super useful, when wanting to group authorisation in one place.

Epicarp answered 7/12, 2020 at 19:35 Comment(0)
C
0

Short answer:

Middleware is more of a global thing while Policies are more localized.

Middleware example: Can user update posts? (most likely by checking if user has permission edit-posts)

Policy example: Can user edit current post? (most likely by checking if $user->id === $post->author_id)

NOTE: While you could put everything in policies - it's way more convenient to use middleware for groups of routes instead of using same checks in multiple policy methods.

Cenac answered 15/9, 2023 at 8:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.