4

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

    <?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)并且我不想多次重写中间件句柄函数。如何在中间件中注入引用模型以使其适应我的应用程序中的多个模型?

4

2 回答 2

3

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

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

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);
}

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

于 2015-08-05T09:18:58.093 回答
3

您可以使用路由和中间件参数

这是中间件(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-08-07T09:20:39.743 回答