【问题标题】:Laravel: How to throw 403 if the user enter the ID manually in the route?Laravel:如果用户在路由中手动输入ID,如何抛出403?
【发布时间】:2018-06-27 14:11:27
【问题描述】:

构建应用程序(博客/帖子)。 只有授权用户可以编辑他们的帖子(当然只属于他们)。 比如 id 为 15 的 Post 属于特定用户,所以如果他编辑它,路由会是这样的

http://localhost:8000/post/15/edit

这是正确的。

但是当用户在路由中输入任何其他帖子ID(不属于他)时,它会显示

http://localhost:8000/post/16/edit

ErrorException (E_NOTICE)
Trying to get property 'user_id' of non-object

这种情况下如何显示未经授权的页面?

这是 postController

public function edit($id)

{

$post = Post::find($id);

        if(Auth::user()->id == $post->user_id){

        return view('post-edit',compact('post'));
    }else {
        return redirect()->route('home');      

}
}

【问题讨论】:

  • 404 is page not found - 您正在寻找 403 禁止。为此,类似于; if ($post_author != $current_user) { exit("Error msg"); } - 我不知道你的变量,所以这是对合理名称的猜测
  • 好的。谢谢!但是在这种情况下如何抛出 403 呢?
  • 您在此实例中遇到的错误是说您在代码中访问的变量 ($user_id) 在您从中访问它的类中不存在 - 请确保已声明并设置它
  • 我已经编辑了我的问题并添加了 PostController

标签: php laravel laravel-5


【解决方案1】:

使用 laravel 授权策略对用户进行授权。

php artisan make:policy PostPolicy --model=Post

此命令将在 app\policies 目录中创建 PostPolicy.php。 现在您必须在 AuthServiceProvider 中注册该策略。例如,首先添加策略和模型的使用语句。

use App\Post;
use App\Policies\PostPolicy;

然后找到受保护的 $policies 并在该数组中注册您的策略。模型遵循政策。

protected $policies = [
    Post::class => PostPolicy::class,
];

现在在我们使用 artisan 命令生成的策略中。将保存所有与 CRUD 相关的方法。他们每个人都接受两个参数,一个是用户,第二个是您要授权的模型,除了创建方法。请注意,您可以修改 create 或其他方法以接受更多参数。由你决定。

现在,例如在您的策略中,让我们为更新方法构建逻辑。

/**
 * Determine if the given post can be updated by the user.
 *
 * @param  \App\User  $user
 * @param  \App\Post  $post
 * @return bool
 */
public function update(User $user, Post $post)
{
    return $user->id === $post->user_id;
}

如您所见,在此处返回布尔值。您可以根据需要自定义方法。接下来在您的控制器方法中。您想要授权用户的地方只需添加

public function update(Post $post)
{
    $this->authorize('update', $post);
    // then your logic here.
}

对于创建授权,您只需传递空类

$this->authorize('create', Post::class);

它接受两个参数,一个是授权方法名称,第二个是模型。它会自动获取认证用户和授权用户。如果未授权,则抛出Illuminate\Auth\Access\AuthorizationException,即 403。

另外,如果您需要修改 403 错误视图,您需要在其中创建 403 刀片

resources/views/errors/403.blade.php

laravel doc. 中的所有内容都有详细记录

额外提示如果您打算使用从数据库返回的一些布尔数据类型值作为 tinyint,即 1 或 0。例如

public function view(User $user, Post $post)
{
    if(! $post->isPrivate) {
       return true;
    }
    return $user->id === $post->user_id;
}

然后确保将该值转换为模型中的布尔值以返回真或假。因为当我在共享主机上部署我的应用程序时它不起作用。后来我发现它以字符串的形式返回。数据库的版本也很旧。

【讨论】:

    【解决方案2】:

    以下代码检查帖子是否存在(这就是您收到错误Trying to get property 'user_id' of non-object 的原因,因为它不存在),然后检查它是否属于处于相同条件的用户。如果它无效,它会以 403 UNAUTHORIZED 错误代码中止。

    public function edit($id)
    {
        $post = Post::find($id);
        if (empty($post) || Auth::id() != $post->user_id) {
            abort(403);
        }
        else {
            return view('post-edit',compact('post'));      
        }
    }
    

    这是一个更好的版本,它检查帖子是否存在,具有指定的 ID,但也具有正确的用户,否则抛出异常:

    public function edit($id)
    {
        $post = Post::whereHas('user', function ($q) {
            $q->where('users.id', Auth::id());
        })->findOrFail($id);
    
        return view('post-edit',compact('post'));      
    }
    

    第三个版本,与第二个想法相同,但更简单:

    public function edit($id)
    {
        $post = Post::where('user_id', Auth::id())->findOrFail($id);
    
        return view('post-edit',compact('post'));      
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-09-28
      • 2017-11-06
      • 1970-01-01
      • 2020-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多