【问题标题】:Use Policies with apiResource Routes将策略与 apiResource 路由一起使用
【发布时间】:2019-11-07 02:05:20
【问题描述】:

目前我正在编写一个 Laravel 5.6 REST api。现在我想保护我的端点:

我的应用程序中的每个用户都有一个角色。基于此,用户应该能够访问某些端点,否则应该会收到 403 错误。为此,我想使用Policies,因为当用作中间件时,它们可以在传入请求甚至到达我的路由或控制器之前授权操作。

我这样声明我的端点:

Route::apiResource('me', 'UserController');

我现在的问题是,如果我想使用Policies 作为中间件,我必须指定像middleware('can:update,post') 这样的(HTTP)方法。当我在路由声明中使用apiResource 时,我应该怎么做?

顺便说一句:目前我已经为每种方法写了一个FormRequest(这很痛苦)并在那里进行授权。切换到Policies中间件后,我可以在authorize方法中简单地return true吗?

【问题讨论】:

    标签: laravel


    【解决方案1】:

    由于您使用FormRequest::class 来验证请求数据,因此最好先检查用户是否有权发出请求。对于 Laravel 5.6,最简洁的解决方案是在资源控制器的 __construct() 方法中手动指定每个策略。

    public function __construct()
    {
        $this->middleware('can:viewAny,App\Post')->only('index');
        $this->middleware('can:create,App\Post')->only('store');
        $this->middleware('can:view,post')->only('show');
        $this->middleware('can:update,post')->only('update');
        $this->middleware('can:delete,post')->only('delete');
    }
    

    如果您在控制器内部验证表单数据而不是使用 FormRequest::class,则更简洁的解决方案是同时授权控制器内部的用户。

    public function store(Request $request)
    {
        $this->authorize('create', Post::class);
        // The user is authorized to make this request...
    
        $request->validate([
            //Validation Rules
        });
        // The form data has been successfully validated...
    
        // Controller logic...
    }
    

    从 Laravel 5.7 开始,您可以使用控制器的 __construct() 方法上的一行代码来完成所有这些操作。

    public function __construct()
    {
        $this->authorizeResource(Post::class, 'post');
    }
    

    【讨论】:

      【解决方案2】:

      您可以定义route groups,具有共同行为(中间件、前缀等)的路由。

      以下应该有效:

      Route::middleware('can:update,post')->group(function () {
          Route::apiResource('me', 'UserController');
          //more routes
      });
      

      您也可以为路由添加前缀:

      Route::middleware('can:update,post')->group(function () {
          Route::prefix('users')->group(function () {
              Route::apiResource('me', 'UserController'); //Translated to ex: /users/me
              Route::prefix('books')->group(function () {
                  Route::apiResource('{book}', 'UserController'); //Translated to ex: /users/me/book_1
              });
          });
      });
      

      P.S:我之前没有使用过资源,但它应该可以完成这项工作

      【讨论】:

        猜你喜欢
        • 2021-07-31
        • 1970-01-01
        • 1970-01-01
        • 2017-01-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-04
        • 2017-08-25
        相关资源
        最近更新 更多