在我Symfony的2个应用程序我有3个不同的用户角色,可以访问后台管理部分:绑定一个路线根据用户角色不同的控制器
role_hierarchy:
ROLE_STAFF: ROLE_USER
ROLE_MODERATOR: ROLE_STAFF
ROLE_ADMIN: ROLE_MODERATOR
对于路线像http://example.org/admin/post/
,我会就像我的应用根据用户角色显示不同的信息,这意味着需要绑定到路由。
处理这个问题的最佳方法是什么?
我曾想过一些解决方案,但没有一个似乎对我来说是很好的:
一个控制器,并在每个动作我只是测试用户角色:
<?php /** * @Route("/admin/post") */ class PostController extends Controller { /** * Lists all post entities. * * @Route("/", name="post_index") * @Template() * @Secure(roles="ROLE_STAFF") */ public function indexAction() { $user = $this->get('security.context')->getToken()->getUser(); if ($this->get('security.context')->isGranted('ROLE_STAFF')) { // Do ROLE_STAFF related stuff } else if ($this->get('security.context')->isGranted('ROLE_MODERATOR')) { // Do ROLE_MODERATOR related stuff } else if ($this->get('security.context')->isGranted('ROLE_ADMIN')) { // Do ROLE_ADMIN related stuff } return array('posts' => $posts); } }
即使是不这项工作,国际海事组织显然不是一个好设计。
一个BackendController其分派到3个不同的控制器:
<?php /** * @Route("/admin/post") */ class PostBackendController extends Controller { /** * Lists all post entities. * * @Route("", name="admin_post_index") * @Template("AcmeBlogBundle:PostAdmin:index.html.twig") * @Secure(roles="ROLE_STAFF") */ public function indexAction() { if ($this->get('security.context')->isGranted('ROLE_STAFF')) { $response = $this->forward('AcmeBlogBundle:PostStaff:index'); } else if ($this->get('security.context')->isGranted('ROLE_MODERATOR')) { $response = $this->forward('AcmeBlogBundle:PostModerator:index'); } else if ($this->get('security.context')->isGranted('ROLE_ADMIN')) { $response = $this->forward('AcmeBlogBundle:PostAdmin:index'); } return $response; } }
同一个号码。
我试图让控制器扩展对方:
<?php /** * @Route("/admin/post") */ class PostStaffController extends Controller { /** * Lists all post entities. * * @Route("/", name="post_index") * @Template() * @Secure(roles="ROLE_STAFF") */ public function indexAction() { $user = $this->get('security.context')->getToken()->getUser(); // Do ROLE_STAFF related stuff return array('posts' => $posts); } } <?php /** * @Route("/admin/post") */ class PostModeratorController extends PostStaffController { /** * Lists all post entities. * * @Route("/", name="post_index") * @Template() * @Secure(roles="ROLE_MODERATOR") */ public function indexAction() { $user = $this->get('security.context')->getToken()->getUser(); // As PostModeratorController extends PostStaffController, // I can either use parent action or redefine it here return array('posts' => $posts); } } <?php /** * @Route("/admin/post") */ class PostAdminController extends PostModeratorController { /** * Lists all post entities. * * @Route("/", name="post_index") * @Template() * @Secure(roles="ROLE_ADMIN") */ public function indexAction() { $user = $this->get('security.context')->getToken()->getUser(); // Same applies here return array('posts' => $posts); } }
IMO这是一个更好的设计,但我不能管理,使其工作。路由系统在匹配的第一个控制器上停止。我想让它自动扮演级联风格的王者(即,如果用户是员工,则转到PostStaffController,否则如果用户是主持人转到PostModeratorController,否则转到PostAdminController)。
在我的BlogBundle中添加一个监听器到kernel.controller,它将完成与编号2相同的工作?
我正在寻找最好的设计和更灵活的解决方案有有,我们在未来增加更多的角色的机会。
我面对完全相同的情况,你有没有找到一个好的解决方案? – 2012-08-07 22:50:00
所有解决方案都很好,但设计不好。 如果您遇到同样的问题,请确保首先对您的应用程序不构成错误概念。在我的情况下,而不是这样做,我为我的实体做了2种不同的表单类型:即“配置”和“定制”。所以管理员可以访问“配置”和“定制”控制器,而员工和主持人只能访问“定制”。 不确定是否清楚。也许我应该把它作为一个完整的答案? – iamdto 2012-08-24 11:08:51
你是对的,这是一个糟糕的设计。我的解决方案是将应用程序的不同区域分开放在不同的包中,我可以相应地管理这些角色。谢谢。 – 2012-09-03 14:36:34