【问题标题】:Laravel policy never called always 403Laravel 政策从不总是调用 403
【发布时间】:2021-12-24 11:27:40
【问题描述】:

Laravel 被用作 API 端点,我试图根据用户类型来控制用户查看网站某些部分的能力。使用 $this->authorizeResource()$this->authorize() 它总是返回 403 而不会影响策略。注释掉应用程序允许访问的行。

AuthServiceProvider

<?php

namespace Project\Providers;

use Project\Entities\Plumber;
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Auth;
use Project\Policies\PlumberPolicy;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        Plumber::class => PlumberPolicy::class
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();
    }
}

PlumberPolicy,为了测试一切都返回 true。

<?php

namespace Project\Policies;

use Project\Entities\User;
use Project\Entities\Plumber;
use Illuminate\Auth\Access\HandlesAuthorization;

class PlumberPolicy
{
    use HandlesAuthorization;

    /**
     * Determine whether the user can view the Plumber.
     *
     * @param  \Project\Entities\User  $user
     * @param  \Project\Entities\Plumber  $plumber
     * @return mixed
     */
    public function view(User $user, Plumber $plumber)
    {
        //
        return true;
    }

    /**
     * Determine whether the user can create Plumbers.
     *
     * @param  \Project\Entities\User  $user
     * @return mixed
     */
    public function create(User $user)
    {
        //
        return true;
    }

    /**
     * Determine whether the user can update the Plumber.
     *
     * @param  \Project\Entities\User  $user
     * @param  \Project\Entities\Plumber  $plumber
     * @return mixed
     */
    public function update(User $user, Plumber $plumber)
    {
        //
        return true;
    }

    /**
     * Determine whether the user can delete the Plumber.
     *
     * @param  \Project\Entities\User  $user
     * @param  \Project\Entities\Plumber  $plumber
     * @return mixed
     */
    public function delete(User $user, Plumber $plumber)
    {
        //
        return true;
    }
}

控制器设置。

namespace Project\Http\Controllers;
class Controller extends BaseController
{
    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}

namespace Project\Http\Controllers;
class ApiController extends Controller
{

    public function index(Request $request) { .... }
    public function show(Request $request, $id) { .... }
    public function store(Request $request) { .... }
    public function create(Request $request) { .... }
    public function edit(Request $request) { .... }
    public function update(Request $request, $id) { .... }
    public function destroy(Request $request, $id) { .... }
}

namespace Project\Http\Controllers;
class PlumberController extends ApiController {
    public function __construct() {
        $this->authorizeResource(\Project\Entities\Plumber::class);
    }

    public function show(Request $request, $id) {
        return parent::show($request, $id);
    }
}

我已经尝试了加载策略并使用类名的字符串声明调用 authorizeResourceauthorize() 以转义和不转义命名空间的所有建议。

单步执行 Xdebug 似乎在 vendor/laravel/framework/src/Illuminate/Auth/Access/Gate.php 上失败了

public function authorize($ability, $arguments = [])
{
    $result = $this->raw($ability, $arguments);

    if ($result instanceof Response) {
        return $result;
    }

    return $result ? $this->allow() : $this->deny();
}

$result = $this-&gt;raw($ability, $arguments); 返回为 false。 $ability = view$arguments = 空数组。

我读过https://github.com/laravel/framework/issues/22847#issuecomment-521308861,其中用户提到需要在方法声明中传递模型,而我无法通过大规模的系统重写来做到这一点。

路线列表是

| GET|HEAD                               | api/plumber                                         | plumber.index                 | Project\Http\Controllers\PlumberController@index                     | api,auth:api,role:valuer,plumber                                   |
| POST                                   | api/plumber                                         | plumber.store                 | Project\Http\Controllers\PlumberController@store                     | api,auth:api,role:valuer,plumber,can:create,Project\Entities\plumber |
| GET|HEAD                               | api/plumber/{plumber}                               | plumber.show                  | Project\Http\Controllers\PlumberController@show                      | api,auth:api,role:valuer,plumber,can:view,plumber                  |
| PUT|PATCH                              | api/plumber/{plumber}                               | plumber.update                | Project\Http\Controllers\PlumberController@update                    | api,auth:api,role:valuer,plumber,can:update,plumber                |
| DELETE                                 | api/plumber/{plumber}                               | plumber.destroy               | Project\Http\Controllers\PlumberController@destroy   

【问题讨论】:

    标签: php laravel-5.8 laravel-middleware policies


    【解决方案1】:

    据我发现,使用authorizeResource() 是不可能的。您需要调用$this-&gt;authorize() 并传入一个对象,因为它会与数组出错。

    class AuthServiceProvider extends ServiceProvider
    {
        protected $policies = [
            Plumber::class => PlumberPolicy::class
        ];
    }
    

    authorize() 需要一个对象,如果传递一个数组会抛出错误。

    class PlumberController extends ApiController
    {
        public function index(Request $request) { 
            $this->authorize('viewAny', \Project\Entities\Plumber::class);
        }
        public function update(Request $request, $id) { 
            $plumber = $this->repository->getByID($id);
    
            $this->authorize('update', $plumber);
        }
        public function store(Request $request) { 
            $this->authorize('create', \Project\Entities\Plumber::class);
        }
        public function show(Request $request, $id) { 
            $plumber = $this->repository->getByID($id);
    
            $this->authorize('update', $plumber);
        }
        public function destroy(Request $request, $id) { 
            $plumber = $this->repository->getByID($id);
            
            $this->authorize('update', $plumber);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-04-05
      • 2021-03-23
      • 1970-01-01
      • 2019-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-23
      • 2020-11-14
      • 2020-09-27
      相关资源
      最近更新 更多