我張貼這種解決方案,以便其他人可以看到我的最終代碼,但在這裏實行的是選民的時候有問題,建議我發現的陷阱。
supportsAttribute:看來,當你調用isGranted
方法上SecurityContext
,它實際上並沒有委託你vote
方法內vote
呼叫到VoterInterface
所以之前檢查這個方法你確實有自己檢查屬性。
supportsClass:在它上面的問題的答案似乎是這種方法可能是一個工廠爲基礎的選擇,其中VoterInterface
S可投票的關鍵,但實際上Symfony2的文件上寫着:
的supportsClass()方法用於檢查選舉器是否支持當前用戶令牌類。
因此,它實際上似乎與Voter
是否支持令牌類型有關。更糟糕的是,PHP Doc似乎很模糊:
檢查選舉器是否支持給定的類。
在任何情況下的主要問題是,這種方法從未被SecurityContext
電話委託給任何選民的vote
方法前檢查 - 即使這種方法是硬編碼到return false
vote
仍將被稱爲!
所以基本上這個故事的寓意似乎是:檢查$attributes
和$object
手動進來的vote
方法。
我的代碼:
services.yml
parameters:
comment_voter.class: Acme\Bundle\CommentBundle\Security\Authorization\Voter\CommentVoter
services:
comment_voter:
class: %comment_voter.class%
arguments: [@service_container]
public: false
tags:
- { name: security.voter }
和選民類:
<?php
namespace Acme\Bundle\CommentBundle\Security\Authorization\Voter;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Acme\Bundle\CommentBundle\Entity\Comment;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* A class to check editing privileges for Comments.
*/
class CommentVoter implements VoterInterface {
const AUTHOR_EDIT_TIME_LIMIT = 300;
private $container;
public function __construct($container) {
$this->container = $container;
}
public function supportsAttribute($attribute) {
return $attribute === 'EDIT';
}
public function supportsClass($class) {
return true;
}
/**
* Checks whether or not the current user can edit a comment.
*
* Users with the role ROLE_COMMENT_MODERATOR may always edit.
* A comment's author can only edit within 5 minutes of it being posted.
*
* {@inheritdoc}
*/
public function vote(TokenInterface $token, $object, array $attributes) {
if (!($object instanceof Comment)) {
return VoterInterface::ACCESS_ABSTAIN;
}
// Only supports 'EDIT' for now.
if (!$this->supportsAttribute($attributes[0])) {
return VoterInterface::ACCESS_ABSTAIN;
}
$user = $token->getUser();
if (!($user instanceof UserInterface)) {
return VoterInterface::ACCESS_DENIED;
}
// Is the token a comment moderator?
if ($this->container->get('security.context')->isGranted('ROLE_COMMENT_MODERATOR')) {
return VoterInterface::ACCESS_GRANTED;
}
// Is the token the author of the post and within the edit window.
$originalRevision = $object->getOriginalRevision();
if ($originalRevision->getAuthor()->equals($user)) {
if (
(time() - $originalRevision->getCreationDate()->getTimestamp())
<= self::AUTHOR_EDIT_TIME_LIMIT
) {
return VoterInterface::ACCESS_GRANTED;
}
}
return VoterInterface::ACCESS_DENIED;
}
}
終於模板:
{% if is_granted('EDIT', comment) %}<a href="#">Edit</a>{% endif %}
我希望這可以幫助未來的其他人,並且非常感謝有問題的指向我的選民的方向。
這聽起來像我所需要的,插入很好,也可以通過安全上下文的isGranted(它也可以在我的前端用於有條件地顯示控件以編輯註釋)訪問。今晚我會給它一個鏡頭,如果它有效,請勾選答案,但看起來你已成爲贏家:)謝謝! – Kasheen
確定實施此解決方案後,我會說這是要走的路,但我會在下面發佈我的代碼,因爲它會幫助任何人,因爲我在創建投票人時發現了很多陷阱,因此希望我的代碼可以充當文檔(儘管我不能保證正確)給其他人。 – Kasheen