我有两个人和托儿所以及他们之间的ManyToMany
关联。
用户可以拥有角色ROLE_MANAGER并成为多个托儿所的经理。
对于他的仪表板上的每一个动作,我需要验证他是否与托儿所相关联,如果我不这样做,他可以修改网址中的苗圃slu and并且可以访问他没有链接的托儿所。
有没有办法检查托儿所经理仪表板中的每个操作,而无需在每个操作中复制/粘贴验证码?
据我所知,Symfony Events(或Voters?)可以做到这一点,但我以前从未使用它们......
编辑:也许用一点代码更容易理解! 所以我的托儿所仪表板功能是:
public function dashboardAction($nursery_slug)
{
//$currentUser = $this->get('security.token_storage')->getToken()->getUser();
$nurseryRepo = $this->getDoctrine()->getRepository('VSCrmBundle:Nursery');
$nursery = $nurseryRepo->findOneBy(array('slug' => $nursery_slug));
// Sometimes may help
if(!$nursery)
{
throw $this->createNotFoundException("The nursery has not been found or you are not allowed to access it.");
}
return $this->render("VSCrmBundle:Manager:dashboard.html.twig", array(
'nursery' => $nursery
));
}
为了保护这个仪表板,我需要验证当前用户是否链接到托儿所,有些想法:
$verification = $nurseryRepo->findOneBy(array('person' => $currentUser));
if(!$verification){throw accessDeniedException();}
但目前我不得不对经理仪表板中的每一个动作进行测试......
答案 0 :(得分:1)
要使这项工作顺利进行,您需要执行两项操作。
首先,你需要一个NurseryVoter:http://symfony.com/doc/current/security/voters.html
类似的东西:
class NurseryVoter extends Voter
{
const MANAGE = 'manage';
protected function supports($attribute, $subject)
{
if (!in_array($attribute, array(self::MANAGE))) {
return false;
}
if (!$subject instanceof Nursery) {
return false;
}
return true;
}
protected function voteOnAttribute($attribute, $nursery, TokenInterface $token)
{
$user = $token->getUser();
if (!$user instanceof User) {
// the user must be logged in; if not, deny access
return false;
}
// Check the role and do your query to verify user can manage specific nursery
根据链接连接所有内容。此时,您的控制器代码将减少为:
$this->denyAccessUnlessGranted('manage', $nursery);
让所有工作先行。之后,使用Kernel:Controller事件将拒绝访问代码从控制器移动到侦听器。按照文档:http://symfony.com/doc/current/event_dispatcher.html
在分配控制器之后但在实际调用控制器操作之前调用控制器侦听器。这里的技巧是如何确定哪个动作实际需要进行检查。有几种方法。有些人喜欢通过添加NurseryManagerInterface来标记实际的控制器类。侦听器检查控制器以查看它是否具有接口。但我真的不在乎。
我喜欢将这种东西直接添加到路线中。所以我可能会:
// routes.yml
manage_nursery:
path: /manage/{nursery}
defaults:
_controller: manage_nursery_action
_permission: CAN_MANAGE_NURSERY
然后,您的听众将检查权限。
更新了有关内核侦听器的更多详细信息。基本上,您注入授权检查器并从请求对象中拉出_permission。
class KernelListener implements EventSubscriberInterface
{
// @security.authorization_checker service
private $authorizationChecker;
public function __construct($authorizationChecker,$nuseryRepository)
{
$this->authorizationChecker = $authorizationChecker;
$this->nurseryRepository = $nuseryRepository;
}
public static function getSubscribedEvents()
{
return [
KernelEvents::CONTROLLER => [['onController']],
];
}
public function onController(FilterControllerEvent $event)
{
$request = $event->getRequest();
$permission = $request->attributes->get('_permission');
if ($permission !== 'CAN_MANAGE_NURSERY') {
return;
}
$nursery = $this->nurseryRepository->find($request->attributes->get('nursery');
if ($this->authorizationChecker->isGranted('MANAGE',$nursery) {
return;
}
throw new AccessDeniedException('Some message');
}