CakePHP授权插件如何授权对索引的访问?

时间:2018-10-29 17:50:00

标签: cakephp authorization cakephp-3.x

我正在将我的应用程序转换为CakePHP 3.6,现在正在使用新的Authorization插件进行工作。我不确定如何检查索引或其他报表之类的授权,在这些授权中没有“资源”传递给can()authorize()函数。

现在,我已经构建了一个ControllerResolver,是从ORMResolver松散复制的,它可以接受控制器对象并根据单数的控制器名称查找策略,因此它们的命名与我正在建立的实体政策。 (也就是说,我的UserPolicy可以具有canIndexcanEdit函数,前者是通过控制器找到的,后者是通过实体找到的。)

这在我可以调用$this->Authorize->authorize($this);的控制器操作中很好用,但在视图中却无法工作,在视图中我希望能够执行以下操作:

if ($this->Identity->can('index', *something*)) {
    echo $this->Html->link('List', ['action' => 'index']);
}

以便仅显示允许执行这些操作的人员的链接。

任何人都知道系统是否有隐式要求将传递到授权功能中的“资源”作为对象的原因吗? (例如,在授权失败的情况下,插件组件将调用get_class($resource),而无需先检查所提供的资源实际上是否是对象。)允许使用字符串(例如\App\Controller\UsersController::class)可以使我的生活更美好简单。如果只是出于疏忽,很高兴为此准备一份PR。

但是授权索引似乎是一个很明显的功能,所以我想知道我是否错过了什么。也许我应该传递表对象,并在实体策略和表策略之间分配授权?但是仅出于此目的在视图中使用表对象似乎违反了关注点分离。也许到目前为止,该插件的使用一直是索引始终公开的事情?

1 个答案:

答案 0 :(得分:1)

为此,您可以使用https://github.com/cakephp/authorization/blob/master/docs/Component.md#automatic-authorization-checks文档中所述的authorizeModel。基本上是在AppController.php加载组件时添加auhtorizeModel参数

$this->loadComponent('Authorization.Authorization', [
    'skipAuthorization' => ['login','token'],
    'authorizeModel' => ['index','add'],
]);

当您配置要由模型授权的动作时,授权服务将使用TablePolicy,因此,如果要为Books授权索引动作,则需要创建BooksTablePolicy并实现方法

<?php
namespace App\Policy;

use App\Model\Table\BooksTable;
use Authorization\IdentityInterface;

/**
 * Books policy
 */

class BooksTablePolicy
{
    public function scopeIndex($user, $query)
    {
        return $query->where(['Books.user_id' => $user->id]);
    }

    public function canIndex(IdentityInterface $identity)
    {
    // here you can resolve true or false depending of the identity required characteristics
        $identity['can_index']=true;
        return $identity['can_index'];
    }
}

这将在请求到达您的控制器之前进行验证,因此您无需在那里进行任何授权。不过,如果您想应用范围策略,如本例所示:

public function index()
{

    $user = $this->request->getAttribute('identity');
    $query = $user->applyScope('index', $this->Books->find()->contain('Users'));
    $this->set('books', $this->paginate($query));
}