Dynamic custom ACL in zend framework?

2019-02-20 19:08发布

问题:

I need a solution where authenticated users are allowed access to certain Controllers/Actions based not on their user type :ie. admin or normal user (although I may add this using standard ACL later) but according to the current status of their user.

For example :

Have they been a member of the site for more than 1 week?

Have they filled in their profile fully?

Actually, now that I think about it, kind of like they have on this site with their priviledges and badges.

回答1:

For dynamic condition-based tests like you are describing, you can use dynamic assertions in your Zend_Acl rules.

For example:

class My_Acl_IsProfileComplete implements Zend_Acl_Assert_Interface
{
    protected $user;

    public function __construct($user)
    {
        $this->user = $user;
    }

   public function assert(Zend_Acl $acl, 
                           Zend_Acl_Role_Interface $role = null,
                           Zend_Acl_Resource_Interface $resource = null,
                           $privilege = null)
    {
        // check the user's profile
        if (null === $this->user){
            return false;
        }
        return $this->user->isProfileComplete();  // for example
    }
}

Then when defining your Acl object:

$user = Zend_Auth::getInstance()->getIdentity();
$assertion = new My_Acl_Assertion_IsProfileComplete($user);
$acl->allow($role, $resource, $privilege, $assertion);

Of course, some of the details depend upon the specifics of what you need to check and what you can use in your depend upon what you store in your Zend_Auth::setIdentity() call - only a user Id, a full user object, etc. And the roles, resources, and privileges are completely app-specific. But hopefully this gives the idea.

Also, since the assertion object requires a user object at instantiation, this dynamic rule cannot be added at Bootstrap. But, you can create the core Acl instance with static rules during bootstrap and then register a front controller plugin (to run at preDispatch(), say) that adds the dynamic assertion. This way, the Acl is fully populated by the time you get to your controllers where presumably you would be checking them.

Just thinking out loud.