【问题标题】:Laravel 5 : multi-model middleware "Owner"Laravel 5:多模型中间件“所有者”
【发布时间】:2015-08-29 05:13:07
【问题描述】:

我想创建一个中间件来检查经过身份验证的用户是否是项目的所有者。对于单个模型,代码很简单,看起来像:

    <?php namespace App\Http\Middleware;

    use Closure;

    class Owner {

        public function handle($request, Closure $next)
        {
            $id = $request->segments()[1]; //get the id parameter
            $model = Model::find($id); // find the model from DB

            if(!$item)
              return 'not found'; //if item not found

            //check if authenticated user is owner
            if($item->user_id == \Auth::id()){ 
              return $next($request);
            }else{
              return 'not allowed';
            }
        }
    }

现在假设我有多个模型(ModelX、ModelY、ModelZ)并且我不想多次重写中间件句柄函数。 如何在中间件中注入引用模型以使其适应我的应用程序中的多个模型?

【问题讨论】:

标签: laravel laravel-5 laravel-middleware


【解决方案1】:

您可以将中间件参数与路由/模型绑定一起使用。假设您有一个帖子资源。

您将定义路线。中间件获取描述您要检查其所有权的资源的参数。

Route::get('/post/{post}', ['middleware' => 'owner:post', 'as' => 'post', 'uses' => 'PostController@showPost']);

然后您将在 RouteServiceProvider.php 中绑定您的模型:

$router->bind('post', function ($value) {
   return Post::where('id', $value)->firstOrFail();
});

最后,您将制作中间件。重要的是要知道绑定在请求对象中变为 $request->post 可用。由于您将资源的名称传递给中间件,因此它成为 handle 方法中的第三个参数。

public function handle($request, Closure $next, $resource)
{
    if ($request->{$resource}->user_id == \Auth::id()) {
      return $next($request);
    }
    return response('not allowed.', 401);
}

我想您也可以通过编程方式找到资源名称,但使用此方法您的资源名称和路线可能会有所不同。

【讨论】:

    【解决方案2】:

    你可以使用 route 和 middleware parameters:

    这是中间件 (app/Http/Middleware/AbortIfNotOwner.php):

    <?php
    
    namespace App\Http\Middleware;
    
    use Closure;
    
    class AbortIfNotOwner
    {
        /**
         * Handle an incoming request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Closure  $next
         * @param  string    $resourceName
         * @return mixed
         */
        public function handle($request, Closure $next, $resourceName)
        {
            $resourceId = $request->route()->parameter($resourceName);
    
            $userId = \DB::table($resourceName)->find($resourceId)->user_id;
    
            if ($request->user()->id != $userId) {
                abort(403, 'Unauthorized action.');
            }
    
            return $next($request);
        }
    }
    

    内部app\Http\Kernel.php

    protected $routeMiddleware = [
         'owner' => 'App\Http\Middleware\AbortIfNotOwner',
    ];
    

    在您的路线文件中 (app/Http/routes.php):

    Route::group(['middleware' => ['owner:articles']], function() {
        // your route
    });
    

    并且可以选择在控制器中调用它:

    public function __construct()
    {
        $this->middleware('owner:articles', ['only' => ['edit', 'update']]);
    }
    

    【讨论】:

    • 我更喜欢这个解决方案。我将使用非常类似的东西。谢谢!
    猜你喜欢
    • 2015-06-26
    • 2018-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多