首页 文章

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

提问于
浏览
1

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

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

我的access_control规则如下:( 4th one doesn't work

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 回答

  • 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函数类似于使用IS_AUTHENTICATED_REMEMBERED和IS_AUTHENTICEN_FULLY与isGranted函数 - 但它们不相同 . 以下显示了不同之处:

    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 Issue: #16096 - Expression engine has_role() function can't process implicit roles

  • 0

    Documentation:

    添加代码以拒绝访问有两种方法可以拒绝访问某些内容:security.yml中的access_control允许您保护URL模式(例如/ admin / *) . 这很容易,但灵活性较差;在您的代码中通过security.authorization_checker服务 .

    你试图使用第一种方式,但它可能只用第二种方式 .

    您需要在控制器中插入代码来执行授权检查

    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()
    {
    }
    

相关问题