用于检查资源是否为用户所有的中间件
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 策略,并且不会自动生成示例策略方法。
我在制作检查用户是否拥有所请求资源的中间件时遇到了一些问题。
例如,如果用户转到 /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 策略,并且不会自动生成示例策略方法。