Symfony2 - 为用户和类别使用控制器安全性

时间:2014-08-06 01:24:57

标签: security symfony controller user-roles

我试图限制用户访问控制器中的CRUD访问权限。

我与用户和类别有双向的OneToOne关系。它的设置只允许1个用户访问1个博客。

我正在通过以另一个与此类别无关的用户身份登录来测试此问题。点击new后,表单会加载我已设置的任何安全性。

推测问题在于传入$ title参数,(尝试将其作为路径变量传递),因为我认为我没有正确设置它。

有人可以指导我做错的事吗?

控制器代码

/**
 * Post controller.
 *
 * @Route("/category")
 */

/**
 * Creates a new Post entity.
 *
 * @Route("/", name="category_create")
 * @Method("POST")
 * @Template("AcmeDemoBundle:Page:new.html.twig")
 */
public function createAction(Request $request, $title)
{
    // User security
    $em = $this->getDoctrine()->getManager();

    $categoryRepository = $em->getRepository('AcmeDemoBundle:Category');

    $category = $categoryRepository->findOneBy(array(
        'title' => '$title',
    ));

    $owner = $category->getUser();

    $currentUser = $this->get('security.context')->getToken()->getUser();

    if ($owner != $currentUser) {
        throw new AccessDeniedException('You do not have access for this');
    }

    // Form creation
    $post = new Post();

    $form = $this->createCreateForm($post);
    $form->handleRequest($request);

    if ($form->isValid()) {
        $em = $this->getDoctrine()->getManager();
        $em->persist($post);
        $em->flush();

        return $this->redirect($this->generateUrl('category_show', array('id' => $post->getId())));
    }

    return array(
        'post' => $post,
        'form' => $form->createView(),
    );
}

类别实体

/**
 * @var integer
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @var string
 *
 * @ORM\Column(name="title", type="string", length=255)
 */
private $title;

/**
 * @var string
 *
 * @Gedmo\Slug(fields={"title"}, unique=false)
 * @ORM\Column(length=255)
 */
private $catslug;

/**
 * @ORM\OneToMany(targetEntity="Post", mappedBy="category")
 */
protected $posts;

/**
 * @ORM\OneToOne(targetEntity="Acme\DemoBundle\Entity\User", inversedBy="cat")
 * @ORM\JoinColumn(name="cat_id", referencedColumnName="id")
 */
protected $user;

用户实体

/**
 * @var integer
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @var string
 *
 * @ORM\Column(name="username", type="string", length=255)
 * @Assert\NotBlank(message="Field cannot be blank")
 */
private $username;

/**
 * @var string
 *
 * @ORM\Column(name="password", type="string", length=255)
 */
private $password;

/**
 * @ORM\Column(type="string", length=255)
 * @Assert\NotBlank()
 */
private $email;

/**
 * @ORM\Column(type="json_array")
 */
private $roles = array();

/**
 * @var bool
 *
 * @ORM\Column(type="boolean")
 */
private $isActive = true;

/**
 * @Assert\NotBlank
 * @Assert\Regex(
 *     pattern="/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?!.*\s).*$/",
 *     message="Use 1 upper case letter, 1 lower case letter, and 1 number")
 */
private $plainPassword;

/**
 * @ORM\OneToOne(targetEntity="Acme\DemoBundle\Entity\Category", mappedBy="user")
 */
private $cat;

1 个答案:

答案 0 :(得分:0)

您可以尝试创建自己的Security Voter来检查用户是否拥有此操作的权限。示例代码:

class CategoryVoter implements VoterInterface
{
    const CREATE = 'create';

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

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

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

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

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

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

            ....
        }

        ...
    }
}

创建行动:

public function createAction(Request $request, $title)
{
    $em = $this->getDoctrine()->getManager();

    $categoryRepository = $em->getRepository('AcmeDemoBundle:Category');

    $category = $categoryRepository->findOneBy([
        'title' => '$title',
    ]);

    ...

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

    ...
}