Symfony2 - 为用户和类别使用控制器安全性
Posted
技术标签:
【中文标题】Symfony2 - 为用户和类别使用控制器安全性【英文标题】:Symfony2 - Using controller security for user and category 【发布时间】:2014-09-28 19:53:59 【问题描述】:我正在尝试限制用户访问控制器中的 CRUD 访问。
我与用户和类别有双向 OneToOne 关系。设置为仅允许 1 个用户访问 1 个博客。
我正在通过以与该类别无关的另一个用户身份登录来对此进行测试。单击新建时,表单会绕过我设置的任何安全性加载。
推测问题在于传入的 $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】:您可以尝试创建自己的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!');
...
【讨论】:
以上是关于Symfony2 - 为用户和类别使用控制器安全性的主要内容,如果未能解决你的问题,请参考以下文章
Symfony2 - 将安全访问控制设置为只允许匿名身份验证