在我目前正在处理的一个项目中,我有这样的嵌套资源
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。
我是所有者,所以按钮显示,我可以修改,但如果其他用户(例如 user_id 2)使用相同的 URL 查看我的位置,他无法修改任何内容,但可以看到该地点。
我发现,如果该用户使用相同的URL,但将user_id更改为我的,那么他可以完全访问该地点并对其进行修改。
所以为了防止这种情况,我添加了另一个条件:Auth::user()->id == $user->id
我想知道的是是否有防止这种行为的解决方案,因为如果我必须保护嵌套资源的每种方法,那么实现起来就会变得冗长而难看。同样当我来到下一个级别时user.place.picture
.我想每次下楼时都需要增加另一层安全性。$picture->place_id == $place->id
等等。
因此,当我打印一个链接以便用户可以使用正确的用户、地点、图片 ID 单击它时,没有什么可以阻止或检查一个 ID 是否已被修改。如果最后一个被修改,则没有问题,因为它将检索另一个元素。但是,如果我们修改父母的 ID,这可能会很危险,尤其是当我在此过程中授予一些访问权限时。
希望有一个简单的解决方案,我错过了!
首先,我认为您根本不需要执行此检查;
$place.user_id == $user.id
因为正如您所发现的,从URL派生的$user
很容易纵,因此该保护没有价值。您已经添加了一个检查,以确保当前登录的User
是Place
的所有者,但这应该是您唯一的检查,您不需要它们。
如果我理解正确,这听起来像是在 Laravel 中使用策略的完美用例。该文档非常全面,但我会尝试为您的特定用例进行总结:
- 生成
Policy
,例如PlacePolicy
- 对于您的用例,在此策略中,您将创建一个接受参数的
update()
方法,即User
(登录用户)和Place
(他们尝试访问的位置) PlacePolicy
上的update()
方法现在可以通过任何方式确定User
是否可以更新Place
所以,它可能看起来像这样;
<?php
namespace AppPolicies;
use AppPlace;
use AppUser;
class PlacePolicy
{
/**
* Determine if the given place can be updated by the User.
*
* @param AppUser $user
* @param AppPlace $place
* @return bool
*/
public function update(User $user, Place $place)
{
return $place->user_id == $user->id;
}
}
这是一个非常简单的检查 - 但您基本上可以在此处执行任何操作来确定给定用户是否可以对另一个模型执行操作。
注意:您需要在服务提供商处注册此政策,请参阅上面链接的文档,了解如何执行此操作
有了这个Policy
,您就可以利用Laravel提供的一系列有用的工具。例如,您可以利用刀片can
指令执行以下操作:
@can('update', $place)
< SHOW THE EDIT BUTTON >
@endcan
您还可以通过Middleware
应用Policy
类,以防止页面首先被访问:
Route::get('/user/{user}/place/{place}' .....)->middleware('can:update,place');
希望这足以让你上路!:)