我在自定义提供商的安全性方面遇到了非常令人不快的 API 平台 行为。 我真的需要一些解释,如果这种行为确实是有意为之,或者它是一个安全缺陷。
在测试过程中,我意识到自定义提供程序是在安全检查之前执行的。 这意味着安全检查是在执行
provide()
方法之后执行的。
首先执行 CallableProvider::provide()
,然后执行 DenyAccessListener::onSecurity()
检查。
响应已正确调整为 401/403。
然而,提供者可以包含非常微妙的逻辑,在用户未经身份验证/授权的情况下不应执行这些逻辑。
想象一下执行一些非常昂贵的操作或抛出异常。因此,通过在提供程序中抛出异常(即,当请求的实体不存在时),即使对于没有正确身份验证的客户端,也会调整响应。
我知道我可以通过在我的提供商中调用
$this->security->isGranted()
来绕过这个问题,但是在这种情况下,在文档中宣传 security 可能会产生很大的误导。
我已经自己实现了 CallableProvider
,在致电 provide()
之前进行安全检查,但是我不确定什么是正确的方法或最佳实践。
示例:
class MyProvider implements ProviderInterface
{
public function __construct(private readonly Security $security) {}
public function provide(Operation $operation, array $uriVariables = [], array $context = [])
{
var_dump($this->security->isGranted('ROLE_API'));
echo "this code should not be executed without security check";
die;
}
}
#[ApiResource(
operations: [
new Get(
uriTemplate: '/my-entity',
provider: MyProvider::class,
),
],
security: "is_granted('ROLE_API')",
)]
class MyEntity
{
public int $id;
}
输出:
curl -X 'GET' \
'http://localhost/api/my-entity' \
-H 'accept: application/json'
bool(false)
this code should not be executed without security check
我认为必须首先执行提供者,因为访问权可能由投票者授予对象。类似的东西:
security: "is_granted('MY_ENTITY_READ', object)"
在您的示例中,只有一个角色需要检查,我们甚至可以在致电提供商之前拒绝访问。但情况并非总是如此。
所以,好吧,我们应该对此保持警惕,但这种行为是故意的。