我們正在使用Symfony2的角色功能來限制用戶訪問我們應用的某些部分。我們的每個用戶實體都有許多具有開始日期和結束日期的訂閱實體,用戶可以購買年度訂閱。向用戶動態添加角色
現在,有沒有一種方法可以根據用戶是否擁有「主動」訂閱來向用戶動態添加角色?在rails中,我只是讓模型處理它是否具有必要的權限,但我知道symfony2實體不應該有權訪問Doctrine。
我知道,你可以從一個實體實例中訪問實體的關聯,但會經歷所有用戶的簽約對象,這似乎unnecessaryly麻煩我。
我們正在使用Symfony2的角色功能來限制用戶訪問我們應用的某些部分。我們的每個用戶實體都有許多具有開始日期和結束日期的訂閱實體,用戶可以購買年度訂閱。向用戶動態添加角色
現在,有沒有一種方法可以根據用戶是否擁有「主動」訂閱來向用戶動態添加角色?在rails中,我只是讓模型處理它是否具有必要的權限,但我知道symfony2實體不應該有權訪問Doctrine。
我知道,你可以從一個實體實例中訪問實體的關聯,但會經歷所有用戶的簽約對象,這似乎unnecessaryly麻煩我。
我想你會做得更好,設置一個自定義選民和屬性。
/**
* @Route("/whatever/")
* @Template
* @Secure("SUBSCRIPTION_X")
*/
public function viewAction()
{
// etc...
}
SUBSCRIPTION_X
角色(aka屬性)需要由自定義選民類來處理。
class SubscriptionVoter implements VoterInterface
{
private $em;
public function __construct($em)
{
$this->em = $em;
}
public function supportsAttribute($attribute)
{
return 0 === strpos($attribute, 'SUBSCRIPTION_');
}
public function supportsClass($class)
{
return true;
}
public function vote(TokenInterface $token, $object, array $attributes)
{
// run your query and return either...
// * VoterInterface::ACCESS_GRANTED
// * VoterInterface::ACCESS_ABSTAIN
// * VoterInterface::ACCESS_DENIED
}
}
您將需要配置和標記您的選民:
services:
subscription_voter:
class: SubscriptionVoter
public: false
arguments: [ @doctrine.orm.entity_manager ]
tags:
- { name: security.voter }
假設您在用戶實體中擁有正確的關係「訂閱」。
你也許可以嘗試類似:
public function getRoles()
{
$todayDate = new DateTime();
$activesSubscriptions = $this->subscriptions->filter(function($entity) use ($todayDate) {
return (($todayDate >= $entity->dateBegin()) && ($todayDate < $entity->dateEnd()));
});
if (!isEmpty($activesSubscriptions)) {
return array('ROLE_OK');
}
return array('ROLE_KO');
}
角色轉變是可以做到的:
$sc = $this->get('security.context')
$user = $sc->getToken()->getUser();
$user->setRole('ROLE_NEW');
// Assuming that "main" is your firewall name :
$token = new \Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken($user, null, 'main', $user->getRoles());
$sc->setToken($token);
但換頁後,供應商的refreshUser函數被調用,有時,作爲這是EntityUserProvider的情況,角色被查詢覆蓋。 您需要一個自定義提供程序來避免這種情況。
我知道。但正如我所說的,我寧願不瀏覽所有訂閱對象,但讓MySQL執行「繁重的工作」,因爲這必須在每個請求中都發生。 (我從來沒有測試過這個,但是對我來說不必要的水合一堆物體似乎更慢,如果我錯了,請糾正我。) – maiwald 2012-01-16 13:46:29
您可以使用form_login的success_handler選項來使用可訪問Doctrine的服務。 在它裏面,在onAuthenticationSuccess函數中,你要求獲得正確的角色。 而且,因爲每次頁面更改都會重新加載角色,所以您使用不刷新用戶的自定義用戶提供程序。 – webda2l 2012-01-16 16:17:00
但是,如果角色在會話期間發生變化,用戶是否需要註銷並重新登錄?我不希望那樣。 – maiwald 2012-01-16 16:27:31
@ webda2l我不明白你的問題 – 2012-01-16 17:06:18
對不起。我會盡量讓它更容易理解。 引發查詢的Voter類僅被用戶或每次頁面加載時調用一次? 在這最後一種情況下,爲了避免重複查詢,最好的方法是在投票功能中使用會話進行管理,不是嗎? – webda2l 2012-01-16 17:32:35
您可以添加緩存機制或根據需要進行優化。 – 2012-01-16 17:34:28