2017-04-14 78 views
1

在一个项目中,我目前的工作,我有嵌套资源这样Laravel嵌套资源安全

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

一切工作正常,我沿着每次传递用户等的ID ...

诀窍是当你来到一个地方,如果这是你的,我显示按钮来编辑和做一些动作。所以我检查$place.user_id == $user.id是否显示按钮。 /user/1/place/2为Place.show:

打一点,因为到例如访问地方煤矿的,我有以下URL后。

我主人这样的按钮显示,我可以修改,但如果另一个用户(USER_ID 2为例)使用相同的URL,看我的地方,他不能改变什么,但可以看到的地方。

我发现那是什么,如果该用户使用相同的URL,但改变USER_ID挖掘那么他就可以完全访问的地方,对其进行修改。

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

什么我不知道是如果有一个解决方案来防止这种行为,因为如果我要保护一个嵌套的资源的每个方法它的变长并且难以执行。当我来到更高层次user.place.picture。我想我每次下去都需要增加一层安全性。 $picture->place_id == $place->id等。

所以,当我打印一个链接,以便用户可以点击它用正确的用户,地点,照片的身份证再没有什么阻止或检查,如果一个ID已被修改。如果最后一个被修改,那么就没有问题,因为它会检索另一个元素。但是,如果我们修改父母的身份证,这可能会很危险,特别是当我一路授予某些访问权限时。

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

+0

检出策略(https://laravel.com/docs/5.4/authorization) – Robert

回答

2

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

$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提供。例如,你可以利用刀片can指令做这样的事情:

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

您还可以通过Middleware申请Policy类,以防止页面首先被访问:

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

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