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

Posted

技术标签:

【中文标题】保护 show() 方法免受用户访问其他用户消息的最佳方法【英文标题】:Best way of protecting the show() method against users accessing other users messages 【发布时间】:2015-08-13 13:59:30 【问题描述】:

好的,所以我有一个基本的消息系统,我已经建立了一个关系,所以我可以调用$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');
        );
    

【问题讨论】:

【参考方案1】:

在最简单的形式中,在您的 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 模型执行与上述代码示例类似的操作。这种方法可以让控制器保持干净,并且如果需要,可以在应用程序的其他地方重新使用逻辑

添加到使用上面指定的数据透视表。这仅适用于收件箱中有消息的用户:

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();

【讨论】:

太棒了,我确实忘记提及的一件事是我正在使用数据透视表 message_users 来存储,该查询看起来如何? @SeriousJelly 所以你的消息实体没有user_id?每条消息是否附加了多个 user_id?发送者和接收者?我认为 id 需要查看架构以更好地帮助查询 酷,我会在回到办公桌后发布方案,但 sender_id 与消息一起存储,然后所有接收者(可以是多个)都存储在 message_users 数据透视表中。我希望这会有所帮助... 这使它更复杂一些。您最终可能会在 eloquent 中使用子查询,或者使用查询构建器执行类似 SELECT message_user JOIN message ON message_id = message_id WHERE message_id = $id AND ( (user_id = sender_id) OR (reciever_id = user_id) ) ...psuedo 之类的操作代码......那不是可运行的查询......但它说明了它应该如何工作。 将我的架构添加到问题中,以防出现其他问题,否则我将尝试您的查询构建器建议,看看会发生什么:) 感谢您的帮助。

以上是关于保护 show() 方法免受用户访问其他用户消息的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章

保护 Azure 存储免受公共 Internet 访问

如何使用公钥保护 Web API 免受未经授权的访问?

保护Exchange OWA免受暴力***

如何保护 Android 代码免受逆向工程? [复制]

保护您的 Android 应用免受模拟位置的影响

如何保护 Web 应用程序免受 cookie 窃取攻击?