保护 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();
好的,所以我有一个基本的消息传递系统,我有一个关系设置,所以我可以调用 $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();