Zend ACL动态断言



我想限制我的用户只能编辑/删除他们添加的评论。我在youtube上找到了一个名叫integral30的人的例子,并按照他的指示做了。现在我的管理员帐户可以编辑/删除所有内容,但我的用户无法访问自己的评论。

这是代码:资源

class Application_Model_CommentResource implements Zend_Acl_Resource_Interface{
public $ownerId = null;
public $resourceId = 'comment';
public function getResourceId() {
    return $this->resourceId;
}
}

角色

class Application_Model_UserRole implements Zend_Acl_Role_Interface{
public $role = 'guest';
public $id = null;
public function __construct(){
    $auth = Zend_Auth::getInstance();
    $identity = $auth->getStorage()->read();
    $this->id = $identity->id;
    $this->role = $identity->role;
}
public function getRoleId(){
    return $this->role;
}
}

断言

class Application_Model_CommentAssertion implements Zend_Acl_Assert_Interface
{
public function assert(Zend_Acl $acl, Zend_Acl_Role_Interface $user=null,
            Zend_Acl_Resource_Interface $comment=null, $privilege=null){
    // if role is admin, he can always edit a comment
    if ($user->getRoleId() == 'admin') {
        return true;
    }
    if ($user->id != null && $comment->ownerId == $user->id){
        return true;
    } else {
        return false;
    }
}
}

在我的ACL中,我有一个名为setDynemicPermissions的函数,它在访问检查插件的preDispatch方法中被调用。

public function setDynamicPermissions() {
    $this->addResource('comment');
    $this->addResource('post');
    $this->allow('user', 'comment', 'modify', new Application_Model_CommentAssertion());
    $this->allow('admin', 'post', 'modify', new Application_Model_PostAssertion());
}
public function preDispatch(Zend_Controller_Request_Abstract $request) 
{
    $this->_acl->setDynamicPermissions();
}

我从我的注释模型中调用ACL-s-isAllowed方法,在这里我返回一个注释对象列表。

public function getComments($id){
    //loading comments from the DB
    $userRole = new Application_Model_UserRole();
    $commentResource = new Application_Model_CommentResource();
    $comments = array();
    foreach ($res as $comment) {
        $commentResource->ownerId = $comment[userId];
        $commentObj = new Application_Model_Comment();
        $commentObj->setId($comment[id]);
        //setting the data
        $commentObj->setLink('');
        if (Zend_Registry::get('acl')->isAllowed($userRole->getRoleId(), $commentResource->getResourceId(), 'modify')) {
            $commentObj->setLink('<a href="editcomment/id/'.$comment[id].'">Edit</a>'.'<a href="deletecomment/id/'.$comment[id].'">Delete</a>');
        }
        $comments[$comment[id]] = $commentObj;
    }
}

有人能告诉我我做错了什么吗?或者,如果我想让我的管理员有权开始发帖,让其他用户有权对他们发表评论,我应该用什么。每个用户都应该有机会编辑或删除自己的评论,管理员应该拥有所有权限。

您似乎以错误的方式使用动态断言,因为您仍在将roleId传递给isAllowed()

这些动态断言真正的作用是获取一个完整的对象并使用它。Zend将通过对对象调用getResourceId()getRoleId()来确定必须使用哪个规则。

因此,您所要做的就是将对象而不是字符串传递给isAllowed():

public function getComments($id){
    //loading comments from the DB
    $userRole = new Application_Model_UserRole();
    $commentResource = new Application_Model_CommentResource();
    $comments = array();
    foreach ($res as $comment) {
        $commentResource->ownerId = $comment[userId];
        $commentObj = new Application_Model_Comment();
        $commentObj->setId($comment[id]);
        //setting the data
        $commentObj->setLink('');
        // This line includes the changes
        if (Zend_Registry::get('acl')->isAllowed($userRole, $commentResource, 'modify')) {
            $commentObj->setLink('<a href="editcomment/id/'.$comment[id].'">Edit</a>'.'<a href="deletecomment/id/'.$comment[id].'">Delete</a>');
        }
        $comments[$comment[id]] = $commentObj;
    }
}

但是可以做得更好

您不必实现一个全新的Application_Model_CommentResource,而是可以像这样使用实际的Application_Model_Comment

// we are using your normal Comment class here
class Application_Model_Comment implements Zend_Acl_Resource_Interface {
    public $resourceId = 'comment';
    public function getResourceId() {
        return $this->resourceId;
    }
    // all other methods you have implemented
    // I think there is something like this among them
    public function getOwnerId() {
        return $this->ownerId;
    }
}

断言将使用这个对象并检索所有者,将其与实际登录的人进行比较:

class Application_Model_CommentAssertion implements Zend_Acl_Assert_Interface {
    public function assert(Zend_Acl $acl, Zend_Acl_Role_Interface $user=null,
        Zend_Acl_Resource_Interface $comment=null, $privilege=null){
    // if role is admin, he can always edit a comment
    if ($user->getRoleId() == 'admin') {
        return true;
    }
    // using the method now instead of ->ownerId, but this totally depends
    // on how one can get the owner in Application_Model_Comment
    if ($user->id != null && $comment->getOwnerId() == $user->id){
        return true;
    } else {
        return false;
    }
}

用法如下:

public function getComments($id) {
    //loading comments from the DB
    $userRole = new Application_Model_UserRole();
    $comments = array();
    foreach ($res as $comment) {
        $commentObj = new Application_Model_Comment();
        $commentObj->setId($comment[id]);
        //setting the data
        $commentObj->setLink('');
        // no $commentResource anymore, just pure $comment
        if (Zend_Registry::get('acl')->isAllowed($userRole, $comment, 'modify')) {
            $commentObj->setLink('<a href="editcomment/id/'.$comment[id].'">Edit</a>'.'<a href="deletecomment/id/'.$comment[id].'">Delete</a>');
        }
        $comments[$comment[id]] = $commentObj;
    }
}

最新更新