Laravel 仅在模型记录属于经过身份验证的用户时才检索它们

Posted

技术标签:

【中文标题】Laravel 仅在模型记录属于经过身份验证的用户时才检索它们【英文标题】:Laravel only retrieve Model Records if they belong to authenticated user 【发布时间】:2017-08-22 16:24:23 【问题描述】:

我正在使用 Laravel 5.4 并有一个名为 Order 的模型。 为了测试,我创建了两个用户和两个订单,每个用户都有一个订单。

我刚刚看到我能够检索不是我当前用户的人的订单。我正在使用Auth::user()->orders 检索用户自己的订单列表。但为了显示特定订单的详细信息,我这样做:

/**
 * Display the specified resource.
 *
 * @param  int  $id
 * @return \Illuminate\Http\Response
 */
public function show($id)

    $order = CustomerOrder::findOrFail($id)->with('products')->get();
    return view('order.show')
        ->with('order', $order);

我在这里错过了什么?是否有中间件或其他东西告诉应用程序只允许访问与经过身份验证的用户关联的订单?

编辑:所以我尝试使用策略 OrderPolicy (CRUD) 来做到这一点。

政策的view()功能:

/**
 * Determine whether the user can view the customerOrder.
 *
 * @param  \App\User  $user
 * @param  \App\CustomerOrder  $customerOrder
 * @return mixed
 */
public function view(User $user, CustomerOrder $customerOrder)

    return $user->id === $customerOrder->user_id;

我已经在AuthServiceProvider.php注册了:

protected $policies = [
    'App\Model' => 'App\Policies\ModelPolicy',
    Adress::class => AdressPolicy::class, //Doesn't work either
    Order::class => OrderPolicy::class
];

我仍然可以检查其他用户的订单。

【问题讨论】:

出于兴趣,您为什么要对一个普通问题投反对票? 【参考方案1】:

如果您想获取属于经过身份验证的用户的订单,请执行以下操作:

CustomerOrder::where('user_id', auth()->user()->id)->with('products')->find($id);

【讨论】:

@AlexeyMezenin 你去把它弄平。该代码符合作者的要求(我认为)。我认为作者只想得到id$id的订单,而不是所有用户的订单。但他没有说清楚(->findOrFail($id)->get() - 我不知道为什么最后是->get() @dev 谢谢,我已经意识到 OP 想要什么。也修复了我的代码。 应该注意这个答案不太理想,因为它要求开发人员记住按 user_id 搜索。关系会强制搜索属于给定用户的订单,并消除忘记添加位置的风险。【参考方案2】:

您有几个选择。我的选择中最好的选择是使用策略。可在此处找到相关文档:

https://laravel.com/docs/5.4/authorization

或者做可以做这样的事情:

/**
 * Display the specified resource.
 *
 * @param  int  $id
 * @return \Illuminate\Http\Response
 */
public function show($id)

    $user = request()->user();

    $order = $user->orders()->with('products')->find($id)->get();

    return view('order.show', compact('order'));

在您的用户模型上具有订单关系功能。


更新回复

根据您提供的政策和资源路线,您应该能够做到:

/**
 * Display the specified resource.
 *
 * @param  int  $id
 * @return \Illuminate\Http\Response
 */
public function show(CustomerOrder $order)

    $this->authorize('view', $order);

    return view('order.show', compact('order'));

【讨论】:

好的,所以我尝试了策略。我现在有一个 OrderPolicy,在 AuthServiceProvider 中注册它并做了:public function view(User $user, CustomerOrder $customerOrder) return $user->id === $customerOrder->user_id; 但它仍然不起作用,我仍然可以检查其他订单。我做错了什么吗? @Scarwolf 请用新代码更新您的问题。 @AlexeyMezenin 请详细说明原因? @Jono20201 完成 @Scarwolf 很高兴听到您成功了。令人惊讶的是,Laravel 有时会为你做如此多的腿部工作。【参考方案3】:

另一种方法是使用定义的关系并告诉它只检索 ID 为 $id 的关系。像这样:

$customerOrder = auth()->user()->orders()->with('products')->find($id);

【讨论】:

@Scarwolf 如果您的目标是通过 ID 获取订单,但前提是它属于用户,请使用此答案中的代码。 @devk 你忘了添加with('products') 部分。 @Jono20201 确实如此。它将查询范围限定为属于经过身份验证的用户的结果。它使用用户模型上的关系来做到这一点。在 Alexey:这是真的 @devk 完美。 +1 这也可以,但我觉得如果 Laravel 的开发人员为此添加了策略,我会这样做。不过还是谢谢你的回答!【参考方案4】:

记住, 首先,您创建策略。 第二个你注册它。 第三,您在普通控制器中使用 $this->authorize('view', $order); 之类的东西。 你错过了第三步,你可以在这里找到文档: [https://laravel.com/docs/5.8/authorization#authorizing-actions-using-policies][1]

【讨论】:

以上是关于Laravel 仅在模型记录属于经过身份验证的用户时才检索它们的主要内容,如果未能解决你的问题,请参考以下文章

获取经过身份验证的用户 Laravel/Lumen Passport

如何使用 API 中间件在 Laravel 中测试 PHPUnit 一个经过身份验证的用户?

Laravel:缓存和经过身份验证的用户

使用 Laravel Passport 获取经过身份验证的用户并授予密码

Laravel:如何使用 eloquent ORM 查找未经过身份验证的用户的信息?

Laravel 5.3 Auth 外观正在更改为默认的经过身份验证的用户