比方说,我们有直接绑定到数据库表的3个主要角色user:ROLE_USER,ROLE_MODERATOR和ROLE_ADMIN.
但是,我们还有一些其他角色,用于Crews组件(参见下面的UML).我用的peformed行动以下角色Crew:ROLE_CREW_BOSS,ROLE_CREW_LEFTHAND,ROLE_CREW_RIGHTHAND,ROLE_CREW_MEMBER.
+----------------+ +------------------+
| users | | crews |
|----------------| |------------------|
| id | | id |
| username <---+ | name |
| password | | +---> cash |
| roles | | +-------------------+ | | ... |
| ... | | | crew_members | | | |
| | | |-------------------| | | |
+----------------+ | | crew_id +--------------+ | |
+----+ user_id | +--------^---------+
| roles | |
| ... | +------------+
| | |
| | | +------------------+
| | | | forum_topics |
| | | |------------------|
| | | | id |
+-------------------+ +---+ crew_id |
| title |
| description |
| ... |
| |
| |
| |
+------------------+
那是基础结构,我希望这部分是清楚的.问题来了......
问题
具有该角色的每个用户ROLE_MODERATOR都可以创建ForumTopic对象,但不能创建设置的对象crew_id,因为该对象对于特定的工作人员是私有的.此外,只有具有该角色的机组成员(也是用户)ROLE_CREW_BOSS,ROLE_CREW_LEFTHAND或者ROLE_CREW_RIGHTHAND可以编辑其机组人员的论坛主题.我如何检查这种复杂性?还有一个Voter?
更新1
我已经解决了50%的问题,但它并不牢固.我已经创建了一个特定于该对象的选民Entity\\ForumTopic.
public function vote(TokenInterface $token, $object, array $attributes)
{
if ($object instanceof ObjectIdentityInterface) {
if ($object->getType() == 'Entity\\ForumTopic') {
/**
* @var Member $member
*/
$member = $token->getUser();
$userTable = new UserTable();
$user = $userTable->getByMember($member);
$userInCrewTable = new UserInCrewTable();
$crewMember = $userInCrewTable->getByUser($user);
if ($crewMember && in_array($crewMember->getRole(), array('boss', 'lefthand', 'righthand'))) {
return self::ACCESS_GRANTED;
}
}
}
return self::ACCESS_ABSTAIN;
}
Run Code Online (Sandbox Code Playgroud)
这里唯一的问题是我没有使用相应的角色,所以我不能使用角色层次结构功能.任何人都有更好的解决方案或改进我目前的解决方案?
谢谢!
斯特芬
Symfony 的默认角色系统是角色绑定到用户。从这个角度来看,在manyToMany表crew_members中拥有角色字段是没有意义的。
您想要的是基于用户和工作人员的授权,因此您应该使用 ACL 功能,并仅将角色用于全局权限。
$objectIdentity = ObjectIdentity::fromDomainObject($forumTopic);
$acl = $aclProvider->createAcl($objectIdentity);
$securityIdentity = UserSecurityIdentity::fromAccount($user);
// grant owner access
$acl->insertObjectAce($securityIdentity, MaskBuilder::MASK_EDIT);
$aclProvider->updateAcl($acl);
Run Code Online (Sandbox Code Playgroud)
(您可以在http://symfony.com/doc/current/cookbook/security/acl.html上查看更多文档。您还可以使用优秀的 https: //github.com/Problematic/ProblematicAclManagerBundle)
您将其与投票者结合起来:
function vote(TokenInterface $token, $object, array $attributes)
{
if ($object instanceof ObjectIdentityInterface) {
if ($object->getType() == 'Entity\\ForumTopic') {
/**
* @var Member $member
*/
$member = $token->getUser();
if(in_array('ROLE_MODERATOR', $member->getRoles() && empty($object->getCrew()) {
return self::ACCESS_GRANTED;
}
// inject security component via dependecy injection
// delegate further check to ACL
if ($this->container['security']->isGranted('EDIT', $object)) {
return self::ACCESS_GRANTED;
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5128 次 |
| 最近记录: |