如何限制对Symfony中特定用户的操作/方法(控制器)的访问?

时间:2015-03-16 11:21:48

标签: php symfony acl fosuserbundle

有没有办法根据用户限制对Symfony中特定路径的访问,即控制器的操作/方法?

我正在实施FOSUserBundle用于用户管理,并且它具有定义权限的角色,如果我有定义角色的用户但是如果我想基于用户限制页面我必须为每个路由创建角色或者是否有任何权限更好的方法。

我已经研究过ACL及其完美但我找不到解决方案,或者我在那里遗漏了一些东西。

寻找一些帮助和想法。

更新

@AJ Cerqueti - 答案可以快速解决,但我正在寻找更好的方法,如果有的话。

更具体地说,可以使用ACL或其他更好的方法为用户分配路径的访问权限。

4 个答案:

答案 0 :(得分:2)

SYMFONY> = 2.6

SYMFONY< = 2.5

对于这样的简单需求,你可以create a security voter完全符合你的需要(由于不易实现,ACL通常也用于复杂的需求)。

然后你可以在你的控制器中使用选民,如文档中所述:

// get a Post instance
$post = ...;

// keep in mind, this will call all registered security voters
if (false === $this->get('security.authorization_checker')->isGranted('view', $post)) {
    throw new AccessDeniedException('Unauthorised access!');
}

另请阅读How to Use Voters to Check User Permissions

基于评论的更新

也许会更好地了解您想要添加此行为的路由数量,但无论如何(如果您想避免在每个控制器中添加@AJCerqueti代码),您可以使用这个简单示例中的Voter :

选民级别:

// src/AppBundle/Security/Authorization/Voter/RouteVoter.php
namespace AppBundle\Security\Authorization\Voter;

use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;    

class RouteVoter implements VoterInterface
{
    private   $routes;

    public function __construct(array $routes = array())
    {
        $this->routes        = $routes;
    }

    public function supportsAttribute($attribute)
    {
        // you won't check against a user attribute, so return true
        return true;
    }

    public function supportsClass($class)
    {
        // your voter supports all type of token classes, so return true
        return true;
    }

    public function vote(TokenInterface $token, $object, array $attributes)
    {
        // get get allowed routes from current logged in user 
        $userRoutes = $token->getUser()->getRoutes();

        // implement as you want the checks and return the related voter constant as below

        if (...) {# your implementation

            return VoterInterface::ACCESS_DENIED;    
        }

        return VoterInterface::ACCESS_ABSTAIN;
    }
}

注册选民:

<service id="security.access.route_voter"
     class="AppBundle\Security\Authorization\Voter\RouteVoter" public="false">
<argument type="collection">
    <argument>route_one</argument>
    <argument>route_two</argument>
</argument>
<tag name="security.voter" />

Now change the access decision strategy accordingly with the docs

这可以满足您的需求吗?

答案 1 :(得分:2)

同意以前的答案,ACL,选民或某种类型或基于角色的解决方案绝对是最佳实践方法,但对于这种边缘情况,建议扩展您的FOSUser以添加一个&#39; slug&#39;字段,然后检查:

if('accessible_slug' !== $this->get('security.context')->getToken()->getUser()->getSlug()) {
throw new AccessDeniedException()
}

这意味着为控制器/操作组设置一个slug,并将其设置给用户。与角色类似,但没有那么多的开销。仍然更喜欢选民和某种角色等级,但希望这会有所帮助。

答案 2 :(得分:1)

您可以使用Symfony2的 AccessDeniedException

use Symfony\Component\Security\Core\Exception\AccessDeniedException;

然后选中登录User By,

if (false === $this->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) {
            throw new AccessDeniedException();
        } else {
Continue;
    }

答案 3 :(得分:0)

app/config/security.yml中有一个access_control:部分。在那里,您可以为特定路径定义访问限制,例如。 - { path: ^/faq/admin, roles: ROLE_FAQ_ADMIN }

path参数是一个正则表达式,因此上面的条目将限制对以/faq/admin开头的任何路径的访问,例如。 /faq/admin/show-something/faq/admin/show-something-else等。只有具有指定角色的用户才能访问这些路径。对于其他用户,将使用HTTP代码403抛出AccessDeniedException

无需更改控制器内的操作中的代码。