Laravel嵌套资源安全性

时间:2017-04-14 08:08:54

标签: laravel laravel-5 model nested nested-resources

在我正在进行的项目中,我已经嵌套了这样的资源

route()->resources('user', 'UserController');
route()->resources('user.place', 'PostController');
route()->resources('user.place.picture', 'PictureController');

一切正常,我每次都传递用户的身份等等......

诀窍是当你来到一个地方,如果这是你的,我会显示按钮进行编辑并采取一些行动。所以我检查$place.user_id == $user.id是否显示按钮。

播放一段时间后,为了访问我的某个地方,我有以下网址:Place {show /user/1/place/2

我是所有者,所以按钮显示,我可以修改,但如果另一个用户(例如user_id 2)使用相同的URL来查看我的位置,他不能修改任何东西,但可以看到该地方。

我发现如果此用户使用相同的URL但将user_id更改为我的,那么他可以完全访问该地点并进行修改。

为了防止这种情况,我添加了另一个条件:Auth::user()->id == $user->id

我想知道的是,是否存在防止此行为的解决方案,因为如果我必须保护嵌套资源的每个方法,那么实现它将变得漫长而难看。当我来到下一级user.place.picture时。我想每次下楼时都需要添加另一层安全保护。 $picture->place_id == $place->id等等。

因此,当我打印链接以便用户可以使用正确的用户点击它时,放置图片ID,然后没有任何阻止或检查是否已修改一个ID。如果修改了最后一个,那么没有问题,因为它将检索另一个元素。但是如果我们修改父母的id就会很危险,特别是当我在途中授予一些访问权限时。

希望有一个我错过的简单解决方案!

1 个答案:

答案 0 :(得分:3)

首先,我认为你根本不需要进行这项检查;

$place.user_id == $user.id

因为正如您所发现的那样,从URL派生的$user可以很容易地被操纵,因此该保护没有价值。您已添加了支票,以确保当前登录的UserPlace的所有者,但这应该是您唯一的支票,您不需要同时检查它们。

如果我理解正确,这听起来像是使用Policies in Laravel的完美用例。文档非常全面,但我会尝试总结一下您的特定用例:

  • 生成Policy,例如PlacePolicy
  • 对于您的使用案例,在此政策中,您将创建一个update()方法,该方法作为参数接受,User(已登录的用户)和Place(他们所在的位置)试图访问)
  • update()上的PlacePolicy方法现在可以通过任何方式确定User是否可以更新Place

所以,它可能看起来像这样;

<?php

namespace App\Policies;

use App\Place;
use App\User;

class PlacePolicy
{
    /**
     * Determine if the given place can be updated by the User.
     *
     * @param  \App\User  $user
     * @param  \App\Place  $place
     * @return bool
     */
    public function update(User $user, Place $place)
    {
        return $place->user_id == $user->id;
    }
}

这是一个非常简单的检查 - 但你可以在这里做任何事情,以确定给定的用户是否可以对另一个模型执行操作。

注意:您需要在ServiceProvider中注册此政策,请参阅上面链接的文档,了解如何执行此操作

使用此Policy,您可以利用Laravel提供的一系列有用工具。例如,您可以使用Blades can指令执行以下操作:

@can('update', $place)
    < SHOW THE EDIT BUTTON >
@endcan

您还可以通过Policy申请Middleware课程,以防止首页被访问:

Route::get('/user/{user}/place/{place}' .....)->middleware('can:update,place');

希望这足以让你顺利上路! :)