保护 show() 方法免受用户访问其他用户消息的最佳方式

Best way of protecting the show() method against users accessing other users messages

好的,所以我有一个基本的消息传递系统,我有一个关系设置,所以我可以调用 $user->messages 来检索用户收件箱消息的数组。我还有一个非常简单的 show 方法,它目前只抓取带有传递给 show() 函数的 id 的消息。

问题是保护 messages/2 URL 的最佳方法是什么,这样用户就不能只在 URL 中键入任何数字并访问其他用户的消息。

我应该使用路由过滤器和基本上 运行 另一个查询来确保用户可以访问消息 ID 还是我可以对关系做些什么,也许检查消息数组的 ID 和如果它存在那么用户必须有访问权限?

public function up()
    {
        Schema::create('messages', function(Blueprint $table) {
            $table->increments('id');
            $table->mediumText('subject');
            $table->text('message');
            $table->boolean('draft');
            $table->integer('sender_id')->unsigned();
            $table->softDeletes();
            $table->timestamps();

            $table->foreign('sender_id')->references('id')->on('users')->onUpdate('cascade');
        });

        Schema::create('message_assets', function(Blueprint $table) {
            $table->increments('id');
            $table->integer('message_id')->unsigned();
            $table->string('filename', 255);
            $table->softDeletes();

            $table->foreign('message_id')->references('id')->on('messages')->onUpdate('cascade');
        });

        Schema::create('message_users', function(Blueprint $table) {
            $table->increments('id');
            $table->integer('message_id')->unsigned();
            $table->integer('user_id')->unsigned();
            $table->integer('read')->default(0);
            $table->string('folder', 255)->nullable();
            $table->softDeletes();

            $table->foreign('message_id')->references('id')->on('messages')->onUpdate('cascade');
            $table->foreign('user_id')->references('id')->on('users')->onUpdate('cascade');
        });
    }

以最简单的形式,在您的 MessagesController 的 show 方法中,您可以向查询添加一个附加参数并获取记录,其中 message_id = 来自 url 的参数和 user_id 在该消息上是经过身份验证的用户的 ID.... 执行类似

的操作
$message = App\Message::where('id', '=', $id)
                      ->where('user_id', '=', Auth::user()->id)
                      ->first();

如果您正在进行更高级的设计并拥有 MessageRepository,则可以在那里提取此逻辑,因此在您的控制器中您可以执行类似

的操作
$this->repository->getById($id);

并且在消息存储库中,getById() 方法将使用 eloquent 模型执行与上述代码示例类似的操作。这种方法允许控制器是干净的,并且如果需要的话可以在应用程序的其他地方重新使用逻辑

已添加以使用上面指定的枢轴 table。这仅适用于收件箱中有邮件的用户:

DB::table('messages')
    ->join('message_users', 'messages.id', '=', 'message_users.message_id')
    ->where('message_users.message_id', $id)
    ->where('message_users.user_id', $userId)
    ->where('message_users.deleted_at', null)
    ->select('messages.*')
    ->first();