首页 > 解决方案 > CakePHP Authorization 插件如何授权访问索引?

问题描述

我正在将我的应用程序转换为 CakePHP 3.6,现在正在使用新的授权插件。我不确定如何检查诸如索引或其他报告之类的授权,其中没有“资源”可以传递给can()orauthorize()函数。

目前,我已经构建了一个ControllerResolver从 中松散复制的ORMResolver,它接受控制器对象并根据单个控制器名称查找策略,因此它们的名称与我正在构建的实体策略相同。(即my UserPolicycan have canIndexand canEditfunctions,前者通过控制器找到,后者通过实体找到。)

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

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

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

任何人都知道系统是否有理由隐含地要求传递给授权函数的“资源”是一个对象?(例如,插件组件get_class($resource)在授权失败的情况下调用,而无需首先检查所提供的资源是否实际上是一个对象。)允许一个字符串(例如\App\Controller\UsersController::class)将使我的生活变得轻松。如果这只是一个疏忽,很高兴为此整理一份公关。

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

标签: cakephpauthorizationcakephp-3.x

解决方案


为此,您可以使用authorizeModel文档https://github.com/cakephp/authorization/blob/master/docs/Component.md#automatic-authorization-checks中所述的. 基本上是在 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));
}

推荐阅读