【问题标题】:What is 'The right way' to authorize this REST API request?授权此 REST API 请求的“正确方法”是什么?
【发布时间】:2026-01-29 13:10:01
【问题描述】:

我正在构建一个 REST Api,但我正坐在这里遇到问题。我绝不是这方面的专家,所以我想学习如何以“正确的方式”(或至少以一种有意义的方式)处理 REST 架构。

我正在构建一个带有 Angular 前端和基于 laravel 的 RESTfull 后端 API 的 Web 应用程序。该应用程序有这 3 个表格:相册、帖子和评论。如果用户是该相册的成员,则他/她可以在相册中写帖子。

可以邀请用户成为相册的成员,然后查看它的所有帖子以及这些帖子的 cmets。如果用户不是(受邀成为)相册的成员,则无法评论该相册中的帖子。

换句话说:如果用户在某个帖子上发表评论,则该帖子必须来自该用户所属的相册。

我的困境是:如何检查/授权此请求?

我的 Eloquent 关系如下:

  • 用户表与相册有多对多关系
  • 相册有很多帖子
  • 帖子有很多 cmets

传入的请求是一个 POST 请求,有 2 个参数:

  • album_id(帖子所在的相册)
  • post_id(用于被评论的帖子)
  • 正文(实际评论本身)

通过 Auth::user() 检索帖子的作者;

我解决这个问题的最初想法是:

  1. 我检查用户所属的所有相册
  2. 构建一个包含找到的用户所属专辑的所有 ID 的数组
  3. 检查 post_id 参数是否在该数组中
  4. 如果不是,用户不能评论,如果是,用户可以评论

到目前为止我的代码:

// Validate the Request Body
$input = $this->request->only([ 'album_id', 'post_id', 'comment' ]);

$validator = Validator::make( $input, [

    'album_id'  => 'required|integer',
    'post_id'   => 'required|integer',
    'comment'   => 'required',

]);

// Authorize the Request
$albumIdList = Auth::user()->albums()->get()->pluck('id')->toArray();

$postIdList = Post::whereIn( 'album_id', $albumIdList )->select('id')->get()->toArray();

if( ! in_array($this->request->get('post_id'), $albumIdList))
    return abort(403);

// Store the new comment
$comment = Comment::create([

    'user_id'   => Auth::user()->id,
    'post_id'   => $input['post_id'],
    'comment'   => $input['comment'],

]);

return $comment;

我认为这可以正常工作,但如果一张专辑有 1000 个帖子怎么办?使用所有帖子 ID 构建数组对于服务器来说变得非常密集......专业公司(如 Facebook、Twitter、Pinterest)如何在他们的 Web 应用程序中解决这个问题?

提前致谢!

【问题讨论】:

    标签: php api rest laravel


    【解决方案1】:

    您正在寻找whereHasexists 方法:

    $allowed = Auth::user()->albums()->whereHas('post', function ($query) {
        $query->where($this->request->only('post_id'));
    })->exists();
    

    另外,没有理由传递album_id。您的代码可以简化为:

    $this->validate($this->request, [
        'post_id' => 'required|integer',
        'comment' => 'required',
    ]);
    
    $allowed = Auth::user()->albums()->whereHas('posts', function ($query) {
        $query->where($this->request->only('post_id'));
    })->exists();
    
    if (! $allowed) return abort(403);
    
    $input = $this->request->only('post_id', 'comment');
    
    return Comment::create($input + ['user_id' => Auth::id()]);
    

    如果你想进一步清理它,你应该查看 Laravel 的 authorization facilities

    【讨论】: