解决问题:
假设你有一个博客系统,用户可以在其中评论你的帖子。你还希望用户能够编辑自己的评论,但不能编辑其他用户的评论。此外,作为管理员用户,你希望自己能够编辑所有评论。
symfony3给出了两种解决方案:
1、Voters:文档地址:https://symfony.com/doc/3.3/security/voters.html
2、ACLs :文档地址:How to Use Access Control Lists (ACLs) (Symfony 3.3 Docs)
根据需要自己选择解决方案
博主本人选择Voters(选民)进行做一个简单记录:
使用Voters检查用户权限
1、Smyfony如何使用Voters
为了更好的使用Voters,你必须了解Symfony如何与他们合作。每次你使用isGranted()在Symfony的授权检查器上使用该方法或者在控制器调用denyAccessUnlessGranted 时,都会调用Voters。
最终,symfony接受所有的Voters的回应,并根据应用程序中定义的策略做出最终决定(允许或拒绝访问资源),策略可以是:affirmative, consensus or unanimous
自定义voter 需要实现VoterInterface 或继承Voter
2、自定义Voter
// src/AppBundle/Security/PostVoter.php
namespace AppBundle\Security;
use AppBundle\Entity\Post;
use AppBundle\Entity\User;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
class PostVoter extends Voter
{
// these strings are just invented: you can use anything
const VIEW = 'view';
const EDIT = 'edit';
protected function supports($attribute, $subject)
{
// if the attribute isn't one we support, return false
if (!in_array($attribute, array(self::VIEW, self::EDIT))) {
return false;
}
// only vote on Post objects inside this voter
if (!$subject instanceof Post) {
return false;
}
return true;
}
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
{
$user = $token->getUser();
if (!$user instanceof User) {
// the user must be logged in; if not, deny access
return false;
}
// you know $subject is a Post object, thanks to supports
/** @var Post $post */
$post = $subject;
switch ($attribute) {
case self::VIEW:
return $this->canView($post, $user);
case self::EDIT:
return $this->canEdit($post, $user);
}
throw new \LogicException('This code should not be reached!');
}
private function canView(Post $post, User $user)
{
// if they can edit, they can view
if ($this->canEdit($post, $user)) {
return true;
}
// the Post object could have, for example, a method isPrivate()
// that checks a boolean $private property
return !$post->isPrivate();
}
private function canEdit(Post $post, User $user)
{
// this assumes that the data object has a getOwner() method
// to get the entity of the user who owns this data object
return $user === $post->getOwner();
}
}
3、Controller中检查权限
// src/AppBundle/Controller/PostController.php
// ...
class PostController extends Controller
{
/**
* @Route("/posts/{id}", name="post_show")
*/
public function showAction($id)
{
// get a Post object - e.g. query for it
$post = ...;
// check for "view" access: calls all voters
$this->denyAccessUnlessGranted('view', $post);
// ...
}
/**
* @Route("/posts/{id}/edit", name="post_edit")
*/
public function editAction($id)
{
// get a Post object - e.g. query for it
$post = ...;
// check for "edit" access: calls all voters
$this->denyAccessUnlessGranted('edit', $post);
// ...
}
}