Symfony2 - 添加控制器安全性以限制用户访问特定的博客

时间:2014-08-05 03:20:00

标签: security symfony user-roles

我正在尝试通过为每个用户使用USER_ROLE来实施安全性来限制对特定博客的访问。每个博客页面都有1个可以发布的所有者。

这是基于我从KNP大学的精彩教程中学到的东西。

http://knpuniversity.com/screencast/symfony2-ep2

我已使用security.yml中的access_control对其进行设置,以根据用户的USER_ROLE限制对每个用户的访问。 (user1可以访问/ job1 / new和/ job1 / create以创建/编辑/删除博客页面上的帖子---只有1个用户可以访问每个博客页面)

access_control:
    - { path: ^/job1/new, roles: [ROLE_USER1, ROLE_ADMIN] }
    - { path: ^/job2/new, roles: [ROLE_USER2, ROLE_ADMIN] }
    - { path: ^/job3/new, roles: [ROLE_USER3, ROLE_ADMIN] }
    - { path: ^/job1/create, roles: [ROLE_USER1, ROLE_ADMIN] }
    - { path: ^/job2/create, roles: [ROLE_USER2, ROLE_ADMIN] }
    - { path: ^/job3/create, roles: [ROLE_USER3, ROLE_ADMIN] }

每个/ jo​​b1,/ job2等都是单独的博客页面。我在Twig中使用if语句来确定哪个用户有权创建/编辑/删除帖子。

{% if is_granted('ROLE_USER1') %}
    <li><a href="{{ path('job1_new') }}">Add New Post</a></li>
{% endif %}

问题是,当我添加更多博客页面时,我需要在访问控制中创建更多路径(例如,/ job4,/ job5等),虽然它确实有效,但它不是理想的解决方案。

我已在下面的链接中详细说明了代码,因为建议在控制器中使用基于Disqus对话的安全性#joe joe&#39;与Ryan Weaver在这里--- http://knpuniversity.com/screencast/symfony2-ep2

我的问题是:

1)现在我已经与User和Category创建了ManyToMany关系,如何在控制器中设置安全性以防止其他用户访问他们没有角色的创建/编辑/删除操作?

2)如何使用此方法隐藏Twig中的选项以进行创建/编辑/删除/还可以使用此方法在access_control中添加什么内容?

2 个答案:

答案 0 :(得分:1)

增长访问控制以使其需要明确包含每个新用户是不现实的。相反,可以使用ROLE_USER仅允许访问编辑/创建任何实体(例如,博客)给认证用户。用户通过身份验证后,控制器可以提供对该用户的博客实体的访问权限。

这需要用户和博客之间的一对多关系。在控制器中,它变得很简单:

...
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;

/**
 * ...
 * @Security("has_role('ROLE_USER')")
 */

class BlogifyController extends Controller
{

   public function blogAction
    {
        $user = $this->getUser();
        $blogs = $user->getBlogs();
    // do your form thing, etc.
    ...
    }
}

答案 1 :(得分:0)

我认为你应该使用Security Bundle中的builtin Voter。因此,您创建一个与用户实体具有1:1关系的博客实体,然后create a Voter service,在vote方法中构建逻辑,在控制器中使用该投票,就是这样。以下是示例示例:

class SomeVoter implements VoterInterface
{
    const CREATE = 'create';
    const EDIT = 'edit';
    const DELETE = 'delete';

    /**
     * @param string $attribute
     * @return bool
     */
    public function supportsAttribute($attribute)
    {
        return in_array($attribute, array(
            self::CREATE,
            self::EDIT,
            self::DELETE
        ));
    }

    /**
     * @param string $class
     * @return bool
     */
    public function supportsClass($class)
    {
        $supportedClass = 'Acme\DemoBundle\Entity\Blog';

        return $supportedClass === $class || is_subclass_of($class, $supportedClass);
    }

    /**
     * @param TokenInterface $token
     * @param object $blog
     * @param array $attributes
     * @return int
     */
    public function vote(TokenInterface $token, $blog, array $attributes)
    {
        ....

        $attribute = $attributes[0];
        $user = $token->getUser();

        switch($attribute) {
            case 'edit':
                if ($user->getId() === $blog->getUser()->getId()) {
                    return VoterInterface::ACCESS_GRANTED;
                }
                break;

            ....
        }

        ...
    }
}

控制器动作:

public function editAction($id)
{
    $blog = ...;

    if (false === $this->get('security.context')->isGranted('edit', $blog)) {
        throw new AccessDeniedException('Unauthorised access!');
    }

    ...
}