laravel authorizeResource 始终拒绝访问
laravel authorizeResource always denies access
我已经为 API 端点创建了一个资源控制器。我也为模型创建了相应的策略。
如果我使用
进行每个方法的授权检查
$this->authorize('delete', $asset);
然后它按预期工作。但是,如果我将以下内容添加到构造中,我总是会收到 403 禁止。不确定我遗漏了什么,因为以下应该对所有方法应用授权。
$this->authorizeResource(Asset::class, 'asset');
这是我的路线:
Route::group(['middleware' => ['auth:api']], function () {
Route::Resource('asset', 'AssetsApiController');
});
我的保单是这样注册的:
protected $policies = [
Asset::class => AssetPolicy::class,
];
我的删除政策方法是
public function delete(User $user, Asset $asset)
{
return true;
}
API 控制器构造函数如下所示:
public function __construct()
{
$this->authorizeResource(Asset::class,'asset');
}
API控制器方法是
public function destroy($assetID)
{
$asset = Asset::findOrFail($assetID);
$asset->delete();
}
我的路线是
| GET|HEAD | api/asset | asset.index | App\Http\Controllers\AssetsApiController@index | api,auth:api |
| POST | api/asset | asset.store | App\Http\Controllers\AssetsApiController@store | api,auth:api,can:create,App\Asset |
| GET|HEAD | api/asset/create | asset.create | App\Http\Controllers\AssetsApiController@create | api,auth:api,can:create,App\Asset |
| PUT|PATCH | api/asset/{asset} | asset.update | App\Http\Controllers\AssetsApiController@update | api,auth:api,can:update,asset |
| DELETE | api/asset/{asset} | asset.destroy | App\Http\Controllers\AssetsApiController@destroy | api,auth:api,can:delete,asset |
| GET|HEAD | api/asset/{asset} | asset.show | App\Http\Controllers\AssetsApiController@show | api,auth:api,can:view,asset |
| GET|HEAD | api/asset/{asset}/edit | asset.edit | App\Http\Controllers\AssetsApiController@edit | api,auth:api,can:update,asset |
| GET|HEAD | assets | | App\Http\Controllers\AssetsController@index | web |
我想我遗漏了一些东西,但我看不到,Telescope 中的登机口显示为已拒绝。唯一奇怪的是 serveNova
中间件似乎是问题的根源。
Time May 8th 2019, 10:51:37 AM (14m ago)
Hostname core-hosp
Ability delete
Result denied
Location /home/vagrant/code/nova/src/Http/Middleware/ServeNova.php:25
Request View Request
Tags Auth:1
我有同样的问题并通过更改控制器方法的签名解决了它。
默认情况下,控制器接收一个整数 $id
来引用模型,而策略直接接收模型实例。我的直觉是无法在控制器和策略之间进行映射。
所以,我建议尝试将您的控制器方法更改为:
public function destroy(Asset $asset)
{
$asset->delete();
}
不知道是不是bug?我没有找到关于这些方法类型签名约定的文档。
2021 年 5 月更新:
您可以将 $id
保留为默认参数,因为您可以通过在找到相关模型实例之后放置授权调用来允许映射 b/t 控制器和策略,就像这样:
public function destroy($id)
{
$post = Post::find($id);//post instance is created b/4 going through policy.
$this->authorize('delete', $post);
$post->delete();
return Post::orderBy('created_at', 'desc')->paginate(3);
}
我在这里描述了我从这个令人厌烦的问题中吸取的教训:https://github.com/laravel/framework/issues/22847#issuecomment-521308861。也许有人会觉得有用。
我发现为 authorizeResource 获取正确的模型标识符参数非常繁琐。当参数丢失或未正确传递时,Policy 之前的步骤会抛出错误(不是 Policy 本身,因为请求永远不会到达 Policy)。在我的例子中,这意味着我的 CheckUserActive 中间件抛出错误,即使错误出在控制器(而不是中间件)的构造函数中。关于 AuthorizeResource 正在寻找的参数的几点说明:
- 必须小写,即使参数声明为大写
您模型中的案例。
- 必须是一个字符串(没有很多示例中使用的定义 $ 的变量。)
- 必须在单引号内。
例如:
$this->authorizeResource(Model::class, 'parameter');
我通过删除第二个参数解决了这个问题:
public function __construct()
{
$this->authorizeResource(Admin::class);
}
我已经为 API 端点创建了一个资源控制器。我也为模型创建了相应的策略。
如果我使用
进行每个方法的授权检查$this->authorize('delete', $asset);
然后它按预期工作。但是,如果我将以下内容添加到构造中,我总是会收到 403 禁止。不确定我遗漏了什么,因为以下应该对所有方法应用授权。
$this->authorizeResource(Asset::class, 'asset');
这是我的路线:
Route::group(['middleware' => ['auth:api']], function () {
Route::Resource('asset', 'AssetsApiController');
});
我的保单是这样注册的:
protected $policies = [
Asset::class => AssetPolicy::class,
];
我的删除政策方法是
public function delete(User $user, Asset $asset)
{
return true;
}
API 控制器构造函数如下所示:
public function __construct()
{
$this->authorizeResource(Asset::class,'asset');
}
API控制器方法是
public function destroy($assetID)
{
$asset = Asset::findOrFail($assetID);
$asset->delete();
}
我的路线是
| GET|HEAD | api/asset | asset.index | App\Http\Controllers\AssetsApiController@index | api,auth:api |
| POST | api/asset | asset.store | App\Http\Controllers\AssetsApiController@store | api,auth:api,can:create,App\Asset |
| GET|HEAD | api/asset/create | asset.create | App\Http\Controllers\AssetsApiController@create | api,auth:api,can:create,App\Asset |
| PUT|PATCH | api/asset/{asset} | asset.update | App\Http\Controllers\AssetsApiController@update | api,auth:api,can:update,asset |
| DELETE | api/asset/{asset} | asset.destroy | App\Http\Controllers\AssetsApiController@destroy | api,auth:api,can:delete,asset |
| GET|HEAD | api/asset/{asset} | asset.show | App\Http\Controllers\AssetsApiController@show | api,auth:api,can:view,asset |
| GET|HEAD | api/asset/{asset}/edit | asset.edit | App\Http\Controllers\AssetsApiController@edit | api,auth:api,can:update,asset |
| GET|HEAD | assets | | App\Http\Controllers\AssetsController@index | web |
我想我遗漏了一些东西,但我看不到,Telescope 中的登机口显示为已拒绝。唯一奇怪的是 serveNova
中间件似乎是问题的根源。
Time May 8th 2019, 10:51:37 AM (14m ago)
Hostname core-hosp
Ability delete
Result denied
Location /home/vagrant/code/nova/src/Http/Middleware/ServeNova.php:25
Request View Request
Tags Auth:1
我有同样的问题并通过更改控制器方法的签名解决了它。
默认情况下,控制器接收一个整数 $id
来引用模型,而策略直接接收模型实例。我的直觉是无法在控制器和策略之间进行映射。
所以,我建议尝试将您的控制器方法更改为:
public function destroy(Asset $asset)
{
$asset->delete();
}
不知道是不是bug?我没有找到关于这些方法类型签名约定的文档。
2021 年 5 月更新:
您可以将 $id
保留为默认参数,因为您可以通过在找到相关模型实例之后放置授权调用来允许映射 b/t 控制器和策略,就像这样:
public function destroy($id)
{
$post = Post::find($id);//post instance is created b/4 going through policy.
$this->authorize('delete', $post);
$post->delete();
return Post::orderBy('created_at', 'desc')->paginate(3);
}
我在这里描述了我从这个令人厌烦的问题中吸取的教训:https://github.com/laravel/framework/issues/22847#issuecomment-521308861。也许有人会觉得有用。
我发现为 authorizeResource 获取正确的模型标识符参数非常繁琐。当参数丢失或未正确传递时,Policy 之前的步骤会抛出错误(不是 Policy 本身,因为请求永远不会到达 Policy)。在我的例子中,这意味着我的 CheckUserActive 中间件抛出错误,即使错误出在控制器(而不是中间件)的构造函数中。关于 AuthorizeResource 正在寻找的参数的几点说明:
- 必须小写,即使参数声明为大写 您模型中的案例。
- 必须是一个字符串(没有很多示例中使用的定义 $ 的变量。)
- 必须在单引号内。
例如:
$this->authorizeResource(Model::class, 'parameter');
我通过删除第二个参数解决了这个问题:
public function __construct()
{
$this->authorizeResource(Admin::class);
}