【问题标题】:What is the difference between Middleware vs Guards vs Gates/Policies in LaravelLaravel 中的 Middleware vs Guards vs Gates/Policies 有什么区别
【发布时间】:2021-04-28 16:40:04
【问题描述】:

谁能帮助我了解何时/如何使用这些?

【问题讨论】:

    标签: php laravel authentication authorization


    【解决方案1】:

    Gate用于添加登录用户访问的逻辑

    策略用于在模型访问级别添加逻辑

    门的例子

    Gate::define('update-post', function (User $user, Post $post) {
        return $user->id === $post->user_id;
    });
    

    https://laravel.com/docs/8.x/authorization#writing-gates

    在这里您可以在门中看到您的 gettin $user 作为回调,以便用户访问门

    政策示例

    运行 php artisan make:policy PostPolicy --model=Post

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

    https://laravel.com/docs/8.x/authorization#generating-policies

    在这里您可以看到 PostPolicy 正在获取 2 个参数 $user$post,这是模型级别的访问权限

    【讨论】:

      【解决方案2】:

      用于为登录用户访问添加逻辑的门 用于在模型访问级别添加逻辑的策略

      【讨论】:

      • 这与另一个答案的前两行逐字相同,但没有标点符号、空格或任何进一步的解释。为什么要打扰?
      【解决方案3】:

      我也想知道这一点,经过阅读后,我得出以下结论:

      中间件

      通常在路由上运行(但您也可以在控制器方法上运行它)并且可以用于过滤或检查传入的请求

      一个例子是auth,它确定尝试请求特定路由的人是否已通过身份验证(登录)到系统。另一个示例是检查请求是否具有特定标头(例如,如果您想检查应用程序是否正在发送 X-MYAPP-CUSTOMHEADER 标头或其他内容)

      如前所述,中间件可以定义在路由(例如web.phpapi.php)或控制器中。

      web.php 中的一个例子:

      // Get all the posts, but only if the user has signed in to the website 
      Route::get('/posts', [PostController::class, 'index'])->middleware('auth');
      

      PostController.php中的一个例子:

      public function __construct() {
          // Apply the `auth` middleware to every function in this controller
          $this->middleware('auth');
          // Apply the `signed` middleware, but only to the functions `download` and `delete`
          $this->middleware('signed', ['only' => ['download', 'delete']]);
      }
      
      

      大门

      Gates 是在您的AuthServiceProvider.php 文件(在App\Providers 文件夹中)中定义的函数,并指定用户可以做什么和不可以做什么。例如:

      Gate::define('delete-post', function (User $user, Post $post) {
          return $user->id === $post->user_id;
      });
      

      然后在您的PostControllerdelete 方法中:

      public function delete(Request $request, Post $post)
      {
          if (Gate::denies('delete-post', $post)) { // Returns true if `$post->user_id` is not the same as `$user->id` (a.k.a the user is not allowed to delete this post)
              abort(403);
          }
      
          $post->delete();
      }
      

      您还可以在刀片模板中使用一些辅助方法:

      @can('delete-post', $post)
          <!-- Show a link to the delete page here -->
      @endcan
      

      (我在下面对此进行了扩展)

      警卫

      Guards 是一种指定用户对请求进行身份验证的方式

      在我正在进行的一个项目中,我的 API 路由上有一个 jwt(JSON Web 令牌)保护。这意味着当我执行auth()-&gt;attempt(['username' =&gt; 'test', 'password' =&gt; 'test']); 之类的操作时,auth() 函数将尝试使用jwt 保护对我进行身份验证。

      auth.php 中指定了要使用的保护。我的目前看起来像这样:

          'guards' => [
              'web' => [
                  'driver' => 'session',
                  'provider' => 'users',
              ],
      
              'api' => [
                  'driver' => 'jwt',
                  'provider' => 'users'
              ],
          ],
      

      因此,在这种情况下,通过浏览器传入的请求将在登录时分配一个会话,而通过 API 调用传入的请求将需要获取/提供令牌来进行身份验证。两者都会在认证时查找users表来检查用户名/密码。

      政策

      策略的工作方式类似于门,但只是应用于特定模型并存储在自己的文件中(在App\Policies

      您可以使用php artisan make:policy PostPolicy -m Post 创建一个。它将创建一个名为 PostPolicy.php 的文件,该文件将创建一堆函数:

      viewAny // Can the user even look at this model? If no, they'll be denied for all the below methods
      view // Can the user look at the specified Post?
      create // Can they create a new Post
      update // Can they edit / update the specified Post?
      delete // Can they (soft) delete the specified Post?
      restore // Can they restore the specified (soft) deleted Post?
      forceDelete // Can they force delete the specified Post?
      

      典型函数如下所示:

      public function viewAny(User $user)
      {
          // If this returns true, then the other methods will be evaluated.
          return $user->can_view_posts;
      }
      
      public function forceDelete(User $user, Post $post)
      {
          // If this returns true, then the user can force delete the post.
          // This depends on viewAny being true
          return $post->user_id == $user->id;
      }
      

      需要注意的是,viewAny 与“查看全部”不同!将viewAny 视为建筑物的前门。如果viewAny 为真,您可以进入大厅,但您不能查看任何房间,除非特定房间的view 也为真。

      我相信您也可以在带有策略的刀片模板中使用 @can

      @can('forceDelete', $post)
          <!-- Show button to force delete a post here -->
      @endcan
      

      反之亦然:

      @cannot('view', $post)
          <!-- Show a greyed out button or something -->
      @cannot
      

      以及用于检查多个权限的@canany

      @canany(['edit', 'delete'])
          <!-- Show something if the user can edit OR delete -->
      @endcanany
      

      结论

      我希望这很有用。在阅读这篇文章时,我当然学到了很多东西。这比我想象的要多,所以值得查看 Laravel 文档,因为我可能在某些方面是正确的,但我可能在其他方面很差。

      【讨论】:

        猜你喜欢
        • 2011-05-23
        • 2015-09-14
        • 2012-05-21
        • 2022-08-17
        • 2014-07-01
        • 2021-07-16
        • 2013-03-18
        • 1970-01-01
        相关资源
        最近更新 更多