具有多个角色要求的Symfony2访问控制

时间:2015-10-02 11:25:28

标签: symfony access-control

在我的网站上,除了一些特定页面(登录,注册,pwd重置)之外,用户需要登录。我已经实现了remember me功能,效果很好。

我想要实现的是,对于管理页面,用户应该admin role and not remembered。为了检查此要求,我在相关的access_control规则中使用了allow_if,但是它拒绝了我的管理员用户的访问权限,虽然会话没有被记住,我可以在调试工具栏上确认该会话有UsernamePasswordToken

我的access_control规则如下:(第4个不能工作

access_control:
    - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/user/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/user/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/admin, allow_if: "has_role('ROLE_ADMIN') and has_role('IS_AUTHENTICATED_FULLY')" }
    - { path: ^/, role: IS_AUTHENTICATED_REMEMBERED }

如果我从相关的访问控制规则中删除and has_role('IS_AUTHENTICATED_FULLY')部分,用户可以通过授权,因此问题似乎就是这部分。

has_role('IS_AUTHENTICATED_FULLY')有什么问题?

  

Symfony版本:2.7.5

2 个答案:

答案 0 :(得分:1)

好吧,我找到了解决问题的解决方法。

官方网站上的

How to use Expressions in Security, Routing, Services, and Validation食谱文章有相关部分,并说明可能使用is_remember_me()is_fully_authenticated()方法检查存在IS_AUTHENTICATED_REMEMBEREDIS_AUTHENTICATED_FULLY角色各自。

  

is_remember_me与检查IS_AUTHENTICATED_REMEMBERED不同

     

is_remember_me和is_authenticated_fully函数与使用isGranted函数的IS_AUTHENTICATED_REMEMBERED和IS_AUTHENTICATED_FULLY类似 - 但它们不相同。以下显示了不同之处:

use Symfony\Component\ExpressionLanguage\Expression;
// ...

$ac = $this->get('security.authorization_checker');
$access1 = $ac->isGranted('IS_AUTHENTICATED_REMEMBERED');

$access2 = $ac->isGranted(new Expression(
'is_remember_me() or is_fully_authenticated()'
));
  

这里,$ access1和$ access2将是相同的值。与IS_AUTHENTICATED_REMEMBERED和IS_AUTHENTICATED_FULLY的行为不同,如果用户通过remember-me cookie进行身份验证,则is_remember_me函数仅返回true,如果用户在此会话期间实际登录(即完全成熟),则is_fully_authenticated仅返回true。

使用该文档部分,我按如下方式修改了访问控制规则,现在可以使用了:

access_control:
    - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/user/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/user/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/admin, allow_if: "has_role('ROLE_ADMIN') and is_fully_authenticated()" }
    - { path: ^/, role: IS_AUTHENTICATED_REMEMBERED }

但是,我仍然认为这是一个问题,并不是预期的行为。所以,我在官方问题跟踪器中打开了一个问题:

Github问题: #16096 - Expression engine has_role() function can't process implicit roles

答案 1 :(得分:0)

Documentation:

  

添加代码以拒绝访问有两种方法可以拒绝访问   东西:

     
      security.yml中的
  1. access_control允许您保护URL模式(例如/ admin / *)。这很容易,但不太灵活;
  2.   通过security.authorization_checker服务在您的代码中
  3.   

你试图使用第一种方式,但只能用第二种方式。

您需要在控制器中执行授权检查,并在其中加入代码

if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) {
    throw $this->createAccessDeniedException();
}

您也可以使用SensioFrameworkExtraBundle并只为控制器添加注释

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;

...

/**
 * @Security("is_granted('IS_AUTHENTICATED_FULLY')")
 */
public function showAction()
{
}