2012-01-16 2 views
14

우리는 Symfony2의 역할 기능을 사용하여 사용자 앱의 특정 부분에 대한 액세스를 제한합니다. 각 사용자 엔티티에는 시작일과 종료일이 많은 가입 엔티티가 있으며 사용자는 연간 가입을 구매할 수 있습니다.사용자에게 역동적으로 역할 추가

이제 '활성'가입 여부에 따라 사용자에게 역할을 동적으로 추가하는 방법이 있습니까? 레일스에서 ​​필요한 권한이 있는지 여부를 모델이 처리하도록하지만 심포니 2 엔티티는 Doctrine에 액세스하지 않아도된다는 것을 알고 있습니다.

나는 당신의 엔티티 인스턴스 내에서 엔티티의 연결을 액세스 할 수 있지만이 모든 사용자의 가입 오브젝트를 통해 갈 것이며 그 날에 unnecessaryly 성가신 것 같습니다 것을 알고있다.

답변

27

나는 당신이 유권자와 속성을 더 잘 설정한다고 생각한다.

/** 
* @Route("/whatever/") 
* @Template 
* @Secure("SUBSCRIPTION_X") 
*/ 
public function viewAction() 
{ 
    // etc... 
} 

SUBSCRIPTION_X 역할 (일명 속성) 사용자 정의 유권자 클래스에 의해 처리 될 필요가있다.

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 } 
+0

@ webda2l 내 질문에 대해 이해할 수 없습니다. –

+0

죄송합니다. 좀 더 이해하기 쉽게하려고 노력하겠습니다. 쿼리를 유도 한 Voter 클래스는 사용자 또는 각 페이지로드시 한 번만 호출됩니까? 이 마지막 경우에 쿼리 반복을 피하기 위해 투표 기능에서 세션을 관리하는 것이 가장 좋습니다. 그렇지 않습니까? – webda2l

+0

캐싱 메커니즘을 추가하거나 적절하게 최적화 할 수 있습니다. –

2

사용자 엔티티에 "가입"이라는 올바른 관계가 있다고 가정합니다. 로, 때로는

$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 함수가 호출되고 : 역할을 변경

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'); 
} 

을 수행 할 수 있습니다 :

당신은 아마 뭔가를 시도 할 수 있습니다 EntityUserProvider의 경우이 역할은 쿼리로 덮어 씁니다. 이 문제를 방지하려면 사용자 지정 공급자가 필요합니다.

+0

나는 알고있다. 하지만 내가 말했듯이 모든 구독 객체를 처리하지는 않지만 MySQL은 모든 요청에 ​​대해 발생해야하므로 '무거운 짐을 싣기'를 수행하게하십시오. (나는 이것을 테스트 해 본 적이 없지만 여러가지 물체를 불필요하게 수분 공급하는 속도가 느린 것 같습니다. 내가 틀렸다면 수정하십시오.) – maiwald

+0

form_login의 success_handler 옵션을 사용하여 Doctrine에 액세스 할 수있는 서비스를 사용할 수 있습니다. 내부에서 onAuthenticationSuccess 함수를 사용하면 올바른 역할을 요청할 수 있습니다. 그리고 각 페이지가 변경 될 때 역할이 다시로드되기 때문에 사용자를 새로 고치지 않는 사용자 지정 사용자 공급자를 사용합니다. – webda2l

+0

하지만 세션 중에 역할이 변경되면 다시 로그 아웃하거나 다시 로그인 할 필요가 없습니까? 나는 그것을 원하지 않을 것이다. – maiwald

관련 문제