laravel - 为什么可选参数通过而删除参数在策略测试中失败?
问题描述
因此,我为我的应用程序创建了一个测试,该模型是应该可以公开访问Subscription
的端点。index
show
我创建了一个资源控制器来处理来自客户端的 I/O,并创建了一个策略来处理授权,但是在这里,我发现了一些看起来有点奇怪的东西。
在控制器内部,我在构造函数上注册了策略,如下所示:
public function __construct()
{
$this->middleware('auth:api')->except(['index', 'show']);
$this->authorizeResource(Subscription::class, 'subscription');
}
然后在策略类中,我修改了默认生成的方法,如下所示:
/**
* Determine whether the user can view any models.
*
* @param \App\Models\User $user
* @return mixed
*/
public function viewAny(?User $user) // <-- notice here I make it optional, the original was required (without "?" mark).
{
return true; // publicly visible
}
当我运行测试时,它通过了。
public function testSubscriptionIndexArePubliclyAccessible()
{
$subscriptions = Subscription::factory(10)->create()->toArray();
$response = $this->get(route('subscriptions.index'));
$response->assertOk();
$response->assertExactJson($subscriptions);
}
但是,如果我从方法中完全删除User $user
参数,测试将失败。
public function viewAny() <-- if I do this, the test fail. Saying that "this action is unauthorized".
{
return true; // publicly visible
}
所以..为什么会这样?
解决方案
在调用策略方法或门功能之前会进行检查。一项检查是是否可以使用用户调用策略方法,canBeCalledWithUser
. 这将检查是否有 auth 用户并返回true
,如果没有则进行其他检查。下一个检查是该方法是否允许来宾用户,methodAllowsGuests
它将使用反射来获取该方法的参数并查看它是否具有类型并且可以为空,但没有参数因此它返回false
。因此,您最终不会调用该方法,而是将其视为不存在,这始终是false
在授权检查方面。
https://github.com/laravel/framework/blob/8.x/src/Illuminate/Auth/Access/Gate.php#L371 @raw -> callAuthCallback -> resolveAuthCallback
https://github.com/laravel/framework/blob/8.x/src/Illuminate/Auth/Access/Gate.php#L530 @resolveAuthCallback
https://github.com/laravel/framework/blob/8.x/src/Illuminate/Auth/Access/Gate.php#L390 @canBeCalledWithUser
https://github.com/laravel/framework/blob/8.x/src/Illuminate/Auth/Access/Gate.php#L416 @methodAllowsGuests
https://github.com/laravel/framework/blob/8.x/src/Illuminate/Auth/Access/Gate.php#L456 @parameterAllowsGuests
- 它没有进入这个方法调用
推荐阅读
- visual-studio-code - 在 VSCODE 中安装 PlatformIO 时出错 - ReadTimeoutError
- python - 连接到 Sharepoint
- sql - 计算每一行的空值加上其他条件
- asp.net-core - Razor 调试器在设置断点时冻结
- vue.js - 如何跳过第三步跳到第四步
- html - 固定在右上角的位置与父 div 相关
- openlayers - 为什么 optionsFromCapabilities 只存在于 WMTS 上?
- c# - 使用视图模型动态绑定 HTML 表 TH 失败
- python - 执行以下代码时出现值错误
- csv - AWK:基于两列的数据后处理