Laravel 政策从来没有调用过总是 403
Laravel policy never called always 403
Laravel 被用作 API 端点,我试图控制用户根据用户类型查看网站某些部分的能力。使用 $this->authorizeResource()
或 $this->authorize()
它总是 returns 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,为了测试,一切都 returns 为真。
<?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);
}
}
我已经尝试了所有关于加载策略和调用 authorizeResource
和 authorize()
的建议,其中包含 class 名称的字符串声明,以转义命名空间和不转义命名空间。
单步执行 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->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
根据我的发现,使用 authorizeResource()
是不可能的。您需要调用 $this->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);
}
}
Laravel 被用作 API 端点,我试图控制用户根据用户类型查看网站某些部分的能力。使用 $this->authorizeResource()
或 $this->authorize()
它总是 returns 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,为了测试,一切都 returns 为真。
<?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);
}
}
我已经尝试了所有关于加载策略和调用 authorizeResource
和 authorize()
的建议,其中包含 class 名称的字符串声明,以转义命名空间和不转义命名空间。
单步执行 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->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
根据我的发现,使用 authorizeResource()
是不可能的。您需要调用 $this->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);
}
}