我试图限制用户访问控制器中的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;
答案 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!');
}
...
}