Laravel 7 将 Sanctum 与 Vue SPA 结合使用时政策无效(或未注册)

Laravel 7 Policy not working (or not registered) using Sanctum with Vue SPA

Laravel 策略未注册。即使策略拒绝任何经过身份验证的用户能够对任何资源执行任何操作的所有能力。

政策示例:

<?php

namespace App\Policies;

use App\Models\Tag;
use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;

class TagPolicy
{
    use HandlesAuthorization;
    /* BELOW EVERYTHING RETURNS FALSE FOR DEBUGGING PURPOSES*/
    public function viewAny(User $user)
    {
        return false;
    }
    public function create(User $user)
    {
        return false;
    }
    /* other methods .... */
}

我尝试按以下方式注册政策:

<?php

namespace App\Providers;

use App\Models\Message;
use App\Models\Role;
use App\Models\User;
use App\Models\Tag;
use App\Models\Test;
use App\Models\Permission;
use App\Policies\MessagePolicy;
use App\Policies\RolePolicy;
use App\Policies\UserPolicy;
use App\Policies\TagPolicy;
use App\Policies\TestPolicy;
use App\Policies\PermissionPolicy;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
// use Illuminate\Support\Facades\Gate;

class AuthServiceProvider extends ServiceProvider
{
    protected $policies = [
        User::class => UserPolicy::class,
        Role::class => RolePolicy::class,
        Message::class => MessagePolicy::class,
        Tag::class => TagPolicy::class,
        Test::class => TestPolicy::class,
        Permission::class => PermissionPolicy::class,
    ];
    public function boot()
    {
        $this->registerPolicies();
    }
}

也试过

<?php

namespace App\Providers;

use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
// use Illuminate\Support\Facades\Gate;

class AuthServiceProvider extends ServiceProvider
{
    protected $policies = [
        'App\Models\User' => 'App\Policies\UserPolicy',
        'App\Models\Role' => 'App\Policies\RolePolicy',
        'App\Models\Message' => 'App\Policies\MessagePolicy',
        'App\Models\Tag' => 'App\Policies\TagPolicy',
        'App\Models\Test' => 'App\Policies\TestPolicy',
        'App\Models\Permission' => 'App\Policies\PermissionPolicy',
    ];
    public function boot()
    {
        $this->registerPolicies();
    }
}

Laravel docs 说,如果策略匹配命名约定(确实匹配),那么我不必注册策略,因为 Laravel 会自动注册它们。

所以我也试过了:

<?php

namespace App\Providers;

use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
// use Illuminate\Support\Facades\Gate;

class AuthServiceProvider extends ServiceProvider
{
    protected $policies = [
    ];

    public function boot()
    {
        $this->registerPolicies();
    }
}

仍然 none 有效。

我正在使用 Sanctum 来验证 SPA。到目前为止,一切正常(例如登录、注销和只允许经过身份验证的用户访问资源),但策略不起作用。

如果用户通过身份验证,he/she 可以访问和修改任何资源,即使在某些情况下策略应该不允许这样做。

// will delete the tag with id 1, even though the user making the request
// may not have the permission for it! Since every method in TagPolicy is
// returning false (I set to false for debugging), this shouldn't happen!
axios.delete('/tag/1'); 

这里是config/auth.php

<?php
return [
    'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'api' => [
            'driver' => 'token',
            'provider' => 'users',
            'hash' => false,
        ],
    ],
    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\User::class,
        ],
    ],
    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
            'throttle' => 60,
        ],
    ],
    'password_timeout' => 10800,
];

感谢任何帮助!!我已经尝试了几天来解决它!

虽然您已经正确注册了政策(并且您是正确的,在遵守命名约定时无需注册政策),但我相信您还需要 authorize your controller actions 您的政策已创建。

上面的 link 概述了您可以执行此操作的所有不同方法,但为了便于解释,我将包括通过控制器执行此操作的方法:

public function update(Request $request, Tag $tag)
{
    $this->authorize('update', $tag);

    // The current user can update the tag...
}

授权方法将在标记策略中调用您的 update 函数,在本例中将 return false.

我不知道你的TagController长什么样子,但如果是resource controller(使用常规索引、显示、创建、存储等功能),你可以添加以下是您 TagController:

的开头
public function __construct()
{
    $this->authorizeResource(Tag::class, 'tag');
}

这基本上可以防止您在每个控制器操作中重复 $this->authorize(...) 函数。

如果您已经授权了您的操作并且这没有帮助,您可能需要分享您的 RoutesTagController 以便我可以进一步调查。