api-platform.com - API 平台 access_control:无法访问私有财产
问题描述
我正在尝试对对象的所有者实施访问控制。我正在使用 LexikJWTAuthenticationBundle,当我将检查限制为角色时,访问控制有效,但在检查对象属性时会引发异常。
我正在使用 composer 在 Symfony 4.3 项目上安装的 API 平台。PHP 是 7.2.19。
我可以通过检查角色成功地限制对登录用户的请求,但是当添加类似“object.owner == user”的内容时,它会失败并显示“hydra:description”:“无法访问私有财产 App\Entity\Vehicle::$所有者”
这是具有相关字段的实体类。
/**
* @ApiResource(
* collectionOperations={"get"={"access_control"="is_granted('ROLE_USER')"}, "post"={"access_control"="is_granted('ROLE_USER')"}},
* itemOperations={"get"={"access_control"="is_granted('ROLE_USER') and object.owner == user"}, "put"={"access_control"="is_granted('ROLE_USER') and previous_object.owner == user"}},
* normalizationContext={"groups"={"vehicle:read"}},
* denormalizationContext={"groups"={"vehicle:write"}}
* )
* @ORM\Entity(repositoryClass="App\Repository\VehicleRepository")
* @ApiFilter(SearchFilter::class, properties={"owner": "exact"})
*/
class Vehicle
{
/**
* @Assert\NotBlank()
* @ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="vehicles")
* @ORM\JoinColumn(nullable=false)
* @Groups({"vehicle:read", "vehicle:write"})
*/
private $owner;
public function getOwner(): User
{
return $this->owner;
}
}
这应该只允许拥有用户获取或更新车辆,但它总是以“hydra:description”失败:“无法访问私有财产 App\Entity\Vehicle::$owner”。
如果我删除了“object.owner == user”注释,但保留了 ROLE_USER 的检查,则允许该操作。
解决方案
有两种方法可以解决这个问题:
- 更改属性所有者的可见性,即“ public owner ”而不是“ private owner ”(注意:不好的做法,因为它违反了封装原则);
而不是 object.owner,只需编写 object.getOwner() 和 previous_object.getOwner()。因为所有者属性是私有的,所以访问它的唯一方法是通过它的访问器,如下所示:
/** * @ApiResource( * collectionOperations={"get"={"access_control"="is_granted('ROLE_USER')"}, "post"={"access_control"="is_granted('ROLE_USER')"}}, * itemOperations={"get"={"access_control"="is_granted('ROLE_USER') and object.getOwner() == user"}, "put"={"access_control"="is_granted('ROLE_USER') and previous_object.getOwner() == user"}}, * normalizationContext={"groups"={"vehicle:read"}}, * denormalizationContext={"groups"={"vehicle:write"}} * ) * @ORM\Entity(repositoryClass="App\Repository\VehicleRepository") * @ApiFilter(SearchFilter::class, properties={"owner": "exact"}) */ class Vehicle { /** * @Assert\NotBlank() * @ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="vehicles") * @ORM\JoinColumn(nullable=false) * @Groups({"vehicle:read", "vehicle:write"}) */ private $owner; public function getOwner(): User { return $this->owner; } }
推荐阅读
- c# - 将部分视图 CheckBox 绑定到模型属性
- c - 关于套接字编程中这个 strncpy 函数的问题
- powershell - Windows 命令行上是否有添加本地打印机端口的命令?
- ansible - 如何使用 win_scheduled_task 设置“停止现有实例”?
- bash - 为什么嵌套的for循环会生成错误的数字?
- mysql - 从 phpmyadmin 导出数据库时没有结果
- javascript - 键入时 Ajax 脚本无法正常工作(keyup)
- oracle - 如何在sql server和Oracle中将列的当前值与同一列的先前值进行比较
- php - 如何在帖子列表页面中检索所有帖子的评论
- git - Fastlane 匹配无法通过 SSH 连接