简体   繁体   English

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

[英]Laravel prevent users from editing/viewing other users' resources

In my laravel app I have multiple user accounts who have resources that are assigned to them.在我的 Laravel 应用程序中,我有多个用户帐户,这些用户帐户拥有分配给他们的资源。 Say, for example, a "payment".例如,说“付款”。 To edit or view a payment a user would visit the /payment/edit/{payment} route (where payment is the payment ID).要编辑或查看付款,用户将访问/payment/edit/{payment}路线(其中payment是付款 ID)。

Although I have an auth filter to stop un-logged in users from accessing this page there is nothing to stop, for example, user 1 from editing user 2's payment.虽然我有一个身份验证过滤器来阻止未登录的用户访问此页面,但没有什么可以阻止的,例如,用户 1 编辑用户 2 的付款。

Is there a filter I can user that checks which user a payment (or any other resource) belongs to prevent this kind of issue?是否有我可以使用的过滤器来检查付款(或任何其他资源)属于哪个用户以防止此类问题?

[I am using Laravel's model bindings which automatically fetches the model specified by the route rather than me get it in the controller using eloquent.] [我正在使用 Laravel 的模型绑定,它会自动获取路由指定的模型,而不是我使用 eloquent 在控制器中获取它。]

No such filter exists by default, however you can easily create one (depending on how your database is set up).默认情况下不存在这样的过滤器,但是您可以轻松创建一个(取决于您的数据库的设置方式)。 Within app/filters.php, you may do something like this:在 app/filters.php 中,您可以执行以下操作:

Route::filter('restrictPermission', function($route)
{
    $payment_id = $route->parameter('payment');

    if (!Auth::user()->payments()->find($payment_id)) return Redirect::to('/');
});

This compares the currently logged in user's payment_id (in your database) to the {payment} argument passed into the route.这会将当前登录用户的 payment_id(在您的数据库中)与传递到路由中的 {payment} 参数进行比较。 Obviously, depending on how your database is set up (for instance if the payment_id is in a separate table) you need to change the conditional.显然,根据您的数据库的设置方式(例如,如果 payment_id 在单独的表中),您需要更改条件。

Then, apply the filter to your route:然后,将过滤器应用于您的路线:

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

One way is to place a where statement in every relevant query.一种方法是在每个相关查询中放置一个 where 语句。 Although not very pretty, it works.虽然不是很漂亮,但它有效。

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

It's also possible to use url filters like seeARMS is suggesting, however I think it's not very elegant.也可以使用如 seeARMS 建议的 url 过滤器,但我认为它不是很优雅。 The most logical place to nest such logic is in the model itself.嵌套此类逻辑的最合乎逻辑的位置是模型本身。 One possibility is to use model events , but this gives you only the option to intercept update, insert or delete statements, not selects.一种可能性是使用模型事件,但这只能让您选择拦截更新、插入或删除语句,而不是选择。 This might change in the future.这在未来可能会改变。 Maybe you could use boot() event, but I'm not sure if this is gonna work.也许您可以使用boot()事件,但我不确定这是否可行。

Last but not least you could use query scopes .最后但并非最不重要的是,您可以使用查询范围

class Payment extends Eloquent {

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

and in the queries you attach the scope并在查询中附加范围

Payment::authuser()->find($id);

You could do this on a base Model and extend from it, so you have that method in all your relevant models.您可以在基本模型上执行此操作并从中扩展,因此您可以在所有相关模型中使用该方法。

Consider using Laravel Policies: https://laravel.com/docs/6.x/authorization#policy-methods考虑使用 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;
    }
}

By policies you can control if given record could be edited by logged user or not.通过策略,您可以控制登录用户是否可以编辑给定记录。

Cheers!干杯!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM