Zend ACL动态断言 [英] Zend ACL Dynamic Assertion

查看:171
本文介绍了Zend ACL动态断言的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



这里是代码:
资源

  class Application_Model_CommentResource实现Zend_Acl_Resource_Interface {
public $ ownerId = null;
public $ resourceId ='comment';

public function getResourceId(){
return $ this-> resourceId;
}
}

角色

  class Application_Model_UserRole实现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 ($ user-> getRoleId()=='admin'){
真正;
}

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的isAllowed方法我返回一个注释对象列表。

  public function getComments($ id){
//从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]);
//设置数据
$ 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 / 。$评论[ID]。>删除< / A>');
}

$ comments [$ comment [id]] = $ commentObj;
}
}

任何人都可以告诉我我做错了什么?
或者如果我想给我的管理员发起职位的权利和其他用户有权对他们发表评论,我该怎么使用?每个用户都应该有机会编辑或删除自己的评论,管理员应该拥有所有权利。

解决方案

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



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

所以你所要做的就是将你的对象传递给 isAllowed()

  public function getComments($ id){
//从DB
$加载注释b $ b $ 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]);
//设置数据
$ commentObj-> setLink('');

//这行包含更改
if(Zend_Registry :: get('acl') - > isAllowed($ userRole,$ commentResource,'modify')){
$ commentObj-> setLink('< a href =editcomment / id /'.$ comment [id]。'> Edit< / a>'。'< a href =deletecomment / id / 。$评论[ID] '>删除< / A>');
}

$ comments [$ comment [id]] = $ commentObj;
}
}



但可以做得更好



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

  //我们正在使用你的普通注释类
class Application_Model_Comment implements Zend_Acl_Resource_Interface {
public $ resourceId ='comment';

public function getResourceId(){
return $ this-> resourceId;
}

//所有其​​他方法你已经实现
//我认为有这样的东西
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){
//如果角色是admin,他可以随时编辑一个注释
if($ user-> getRoleId()=='admin'){
return true;
}

//现在使用方法而不是 - > ownerId,但这完全取决于
//如何在Application_Model_Comment中获取所有者
if ($ user-> id!= null&& $ comment-> getOwnerId()== $ user-> id){
return true;
} else {
return false;
}
}

使用方法如下:

  public function getComments($ id){
//从DB中加载注释

$ userRole = new Application_Model_UserRole();

$ comments = array();
foreach($ res as $ comment){
$ commentObj = new Application_Model_Comment();
$ commentObj-> setId($ comment [id]);
//设置数据
$ commentObj-> setLink('');

// no $ commentResource,只是纯$ 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;
}
}


I want to restrict my users to edit/delete only the comments which they added. I found an example on youtube by a guy named intergral30 and followed his instruction. And now my admin account has the possibility to edit/delete everything, but my user has no access to his own comment.

Here's the code: Resource

class Application_Model_CommentResource implements Zend_Acl_Resource_Interface{
public $ownerId = null;
public $resourceId = 'comment';

public function getResourceId() {
    return $this->resourceId;
}
}

Role

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

Assertion

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

}

In my ACL I have a function named setDynemicPermissions, which is called in an access check plugin's preDispatch method.

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

And I'm calling the ACL-s isAllowed method from my comment model where I return a list of comment objects.

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

Can anyone tell me what have I done wrong? Or what should I use if I want to give my admins the right to start a post and other users the right to comment on them. Each user should have the chance to edit or delete his own comment and an admin should have all rights.

解决方案

You seem to be using the dynamic assertions in a wrong manner, as you are still passing the roleId to isAllowed().

What these dynamic assertions really do, is take a complete object and work with it. Zend will determine which rule has to be used by calling getResourceId() and getRoleId() on your objects.

So all you have to do is pass your objects instead of the strings to 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;
    }
}

But in can be done better

You would not have to implement a total new Application_Model_CommentResource, but instead you can use your actual Application_Model_Comment like this:

// 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;
    }
}

Assertion would then use this object and retrieve the owner to compare it with the actually logged in person:

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

And the usage is like this:

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

这篇关于Zend ACL动态断言的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆