Laravel阻止用户编辑/查看其他用户'资源


Laravel prevent users from editing/viewing other users' resources

在我的laravel应用程序中,我有多个用户帐户,他们拥有分配给他们的资源。例如,"付款"。要编辑或查看付款,用户将访问/payment/edit/{payment}路由(其中payment是付款ID)。

虽然我有一个身份验证过滤器来阻止未登录的用户访问这个页面,但是没有什么可以阻止的,例如,用户1编辑用户2的付款。

是否有一个过滤器,我可以检查哪个用户支付(或任何其他资源)属于防止这种问题?

[我使用Laravel的模型绑定,它会自动获取路由指定的模型,而不是使用eloquent在控制器中获取模型]

默认情况下不存在这样的过滤器,但是您可以轻松地创建一个(取决于数据库的设置方式)。在app/filters.php中,你可以这样做:

Route::filter('restrictPermission', function($route)
{
    $payment_id = $route->parameter('payment');
    if (!Auth::user()->payments()->find($payment_id)) return Redirect::to('/');
});

将当前登录用户的payment_id(在数据库中)与传入路由的{payment}参数进行比较。显然,取决于数据库的设置方式(例如,如果payment_id在一个单独的表中),您需要更改条件。

然后,对你的路由应用过滤器:

Route::get('/payment/edit/{payment}', array('before' => 'restrictPermission'));

一种方法是在每个相关查询中放置where语句。虽然不是很漂亮,但它可以工作。

$payment = Payment::where('user_id', '=', Auth::user()->id)->find($id);

也可以像seeARMS建议的那样使用url过滤器,但是我认为它不是很优雅。嵌套这种逻辑的最合乎逻辑的位置是模型本身。一种可能性是使用模型事件,但这只提供了拦截更新、插入或删除语句的选项,而不是选择。这在未来可能会改变。也许你可以使用boot()事件,但我不确定这是否会起作用。

最后但并非最不重要的是,您可以使用查询范围。

class Payment extends Eloquent {
    public function scopeAuthuser($query)
    {
        return $query->where('user_id', '=', Auth::user()->id);
    }
}

和在查询中附加

作用域
Payment::authuser()->find($id);

你可以在一个基本模型上这样做,并从它扩展,所以你在所有相关的模型中都有那个方法。

考虑使用Laravel策略:https://laravel.com/docs/6.x/authorization policy-methods

<?php
namespace App'Policies;
use App'Post;
use App'User;
class PostPolicy
{
    /**
     * Determine if the given post can be updated by the user.
     *
     * @param  'App'User  $user
     * @param  'App'Post  $post
     * @return bool
     */
    public function update(User $user, Post $post)
    {
        return $user->id === $post->user_id;
    }
}

通过策略你可以控制给定的记录是否可以被登录用户编辑。

干杯!