Using a single policy method to cover every action

2019-08-30 07:18发布

I have a resource named Post. Every Post is related to a single User, and a User may have several (or zero) Posts.

I'm using Route::resource to map routes for every possible action on the Post resource to a single resource controller, PostController.

Now, I wish to implement a policy for the Post resource. Aiming to keep everything as simple and fool-proof as possible, I'd like to make the policy as follows:

  • Every user is authorized to make any action that doesn't require an existing Post (e.g. create).
  • A User is only authorized to access its own Posts for every action that accesses a Post (e.g. edit, update, delete).

What I'm trying to do right now is to create a single policy method called access, which would check that the Post is owned by the User. Then, in my PostController, every method that has a Post object in its parameters (such as edit(Post $post)) would begin with

$this->authorize('access', $post);

However, I don't like that I need to put those lines manually. If I ever forget one of those, I'll have a security hole right there.

On the other hand, I have the authorizeResource method, which makes authorization automatic but requires the policy to have several methods so they are mapped to the each of the controller's methods. Also, I tried to use the Authorize/can middleware, but it didn't work (maybe because I used it on a Route::resource mapping).

The question is: What would be the cleanest and more secure way to achieve the result I described (i.e. authorizing every possible action that accesses a resource with the exact same rule)?

1条回答
爷、活的狠高调
2楼-- · 2019-08-30 07:51

You can use authorizeResource() and override the resourceAbilityMap() method in your controller. The latter method returns a mapping from controller methods to the policy methods that will be called.

https://github.com/laravel/framework/blob/5.7/src/Illuminate/Foundation/Auth/Access/AuthorizesRequests.php#L105

E.g.

class MyController extends Controller
{
    // ...

    /**
     * Get the map of resource methods to ability names.
     *
     * @return array
     */
    protected function resourceAbilityMap()
    {
        return [
            'edit' => 'access',
            'update' => 'access',
            'destroy' => 'access',
        ];
    }

    // ...
}
查看更多
登录 后发表回答