首页 > 解决方案 > Laravel Policy 不适用于路由中间件

问题描述

我有NotificationPolicy以下代码:

<?php

namespace App\Policies;

use App\Notification;
use App\User;
use Illuminate\Auth\Access\HandlesAuthorization;

class NotificationPolicy
{
    use HandlesAuthorization;

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

我已通过将其添加到以下内容来正确注册AuthServiceProvider

protected $policies = [
    Notification::class => NotificationPolicy::class,
];

我有这个,只有登录的用户才能通过将archived_at值或read_at值设置为当前时间戳等操作来更新他们的通知。如果我在控制器中使用该策略,该策略确实有效,即;

class ArchiveItemController extends Controller
{
    public function __invoke(Notification $notification)
    {
        $this->authorize('update', $notification);
        $notification->markAsArchived();

        return redirect()->route('inbox.index')->with('success', 'Item has been archived');
    }
}

但是我不想在控制器中使用它们,而是希望在我的路由文件中使用它们。所以我$this->authorize('update', $notification);从控制器中删除了这条线,我尝试了以下方法,但它不起作用:

Route::prefix('inbox')->middleware(['auth', 'can:employee'])->group(function () {
    Route::get('/notification/{notification}/archive', 'User\Account\Inbox\ArchiveItemController')
       ->name('inbox.item.archive')
       ->middleware('can:update', 'notification');
});

我什至运行了以下内容,但它们没有任何区别:

php artisan optimize
php artisan cache:clear
php artisan route:cache
php artisan view:clear
php artisan config:cache

标签: laravelroutesauthorizationmiddlewarepolicy

解决方案


您的中间件声明不正确。

您必须更改'can:update', 'notification''can:update,notification'才能正常工作:

所以最后你会得到以下内容:

Route::prefix('inbox')->middleware(['auth', 'can:employee'])->group(function () {
    Route::get('/notification/{notification}/archive', 'User\Account\Inbox\ArchiveItemController')
        ->name('inbox.item.archive')
        ->middleware('can:update,notification');
});

如果您已缓存路由,则必须运行php artisan route:clear以使更改生效。

文档

Laravel 包含一个中间件,它可以在传入请求到达您的路由或控制器之前授权操作。默认情况下,Illuminate\Auth\Middleware\Authorize中间件被分配给 你的类can中的键。App\Http\Kernel让我们探讨一个使用can中间件授权用户可以更新博客文章的示例:

use App\Post;

Route::put('/post/{post}', function (Post $post) {
    // The current user may update the post...
})->middleware('can:update,post');

在这个例子中,我们向can中间件传递了两个参数。第一个是我们希望授权的操作的名称,第二个是我们希望传递给策略方法的路由参数。在这种情况下,由于我们使用隐式模型绑定Post模型将被传递给策略方法。如果用户无权执行给定的操作,403中间件将生成带有状态码的 HTTP 响应。


推荐阅读