用于检查资源是否为用户所有的中间件

Middleware for checking if resource is owned by user

我在制作检查用户是否拥有所请求资源的中间件时遇到了一些问题。

例如,如果用户转到 /playlists/1/edit,并且他们不拥有播放列表 1,则应该显示 401 错误。

这是我目前的情况:

class CheckOwnership {

    public function handle(Request $request, Closure $next)
    {
        if (Playlist::find($request->route()->parameters()['playlists'])->user_id !== $request->user()->id)
        {
            return response('Unauthorized.', 401);
        }

        return $next($request);
    }

}

这太糟糕了,只适用于播放列表资源,但我找不到更好的方法。

谢谢

目前,Laravel 5不支持向中间件传递参数。我改用会话。

在您的播放列表控制器上,获取播放列表的所有者并将其存储在会话中。假设您有一个播放列表 table,其中包含列 userID 和 playlistID。

public function __construct($playlistID){
    $owner = Playlist::where('playlistID',$playlistID)->pluck('userID');
    Session::put('OWNER',$owner);
    $this->middleware('CheckOwnership',['only'=>'edit']); // apply it to edit function only, assuming you are using a route resource
}

然后,只需在您的中间件句柄函数中检索它即可。

public function handle(Request $request, Closure $next)
{
    if (Session::get('OWNER') != $request->user()->id)
    {
        return response('Unauthorized.', 401);
    }

    return $next($request);
}

到目前为止,这是一个简单的解决方法。我们必须等到 Otwell 考虑类似过滤器的中间件。希望这对您有所帮助!

这可以通过新添加的表单请求验证轻松实现。

您可以在此处详细查看(授权表单请求): http://laravel.com/docs/5.0/validation#form-request-validation

给出的示例实际上是关于用户试图编辑他们拥有的评论。

摘录:

The form request class also contains an authorize method. Within this method, you may check if the authenticated user actually has the authority to update a given resource. For example, if a user is attempting to update a blog post comment, do they actually own that comment?

在您的情况下,如果他们不拥有播放列表,只需从授权方法中 return false。

对于那些使用 Laravel 8 的人,我建议使用 Policies。这将使您可以组织特定模型的授权逻辑(e.x。@ntzm 的播放列表模型)。

所以比如可以生成一个PlaylistPolicyclass,

php artisan make:policy PlaylistPolicy --model=Playlist

然后 update 函数可能如下所示。

public function update(User $user, Playlist $playlist)
{
    return $user->id === $playlist->user_id;
}

有多种方法可以执行此政策。如果您想使用中间件,Laravel 有可以执行策略的 can 中间件,因此不需要编写新的中间件。在您的路线文件中,这看起来像这样,

Route::put('playlists/{playlist}/edit', ...)
    ->middleware(['can:update,playlist']);

注意:如果未使用 --model 选项,则必须手动 registered 策略,并且不会自动生成示例策略方法。