在我正在进行的项目中,我已经嵌套了这样的资源
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就会很危险,特别是当我在途中授予一些访问权限时。
希望有一个我错过的简单解决方案!
答案 0 :(得分:3)
首先,我认为你根本不需要进行这项检查;
$place.user_id == $user.id
因为正如您所发现的那样,从URL派生的$user
可以很容易地被操纵,因此该保护没有价值。您已添加了支票,以确保当前登录的User
是Place
的所有者,但这应该是您唯一的支票,您不需要同时检查它们。
如果我理解正确,这听起来像是使用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');
希望这足以让你顺利上路! :)