josegonzalez / cakephp-sanction
使用 Sanction 插件将所有权限集中在一个文件中。
Requires
This package is auto-updated.
Last update: 2024-08-29 04:14:22 UTC
README
用于 CakePHP 的 Sanction 插件
使用 Sanction 插件将所有权限集中在一个文件中。
背景
Sanction 是 CakePackages 上的大量身份验证工作的成果。我使用的是 CakePHP Authsome 插件进行应用程序身份验证,但需要类似 Auth 的授权功能。虽然可以使用 Auth 组件,但感觉既麻烦又难以使用。为了不将权限分散到多个控制器中,并包含复杂的规则,我创建了 PermitComponent 来将这些集中到一个 permit.php
文件中。
要求
- CakeSession 访问的用户会话
- CakePHP 2.x
安装
[使用 Composer]
将插件添加到项目的 composer.json
文件中 - 例如
{
"require": {
"josegonzalez/cakephp-sanction": "2.1.0"
}
}
因为这个插件在其自己的 composer.json
中设置了类型 cakephp-plugin
,所以 composer 会将其安装到你的 /Plugins
目录中,而不是常规的 vendors 文件中。建议你将 /Plugins/DebugKit
添加到你的 .gitignore 文件中。(为什么? 阅读此内容。)
[手动]
- 下载此内容:https://github.com/josegonzalez/cakephp-sanction/zipball/master
- 解压缩下载文件。
- 将生成的文件夹复制到
app/Plugin
- 将你刚刚复制的文件夹重命名为
Sanction
[GIT 子模块]
在应用程序目录中输入
git submodule add git://github.com/josegonzalez/cakephp-sanction.git Plugin/Sanction
git submodule init
git submodule update
[GIT Clone]
在插件目录中输入
git clone git://github.com/josegonzalez/cakephp-sanction.git Sanction
启用插件
在 2.0 版本中,您需要在 app/Config/bootstrap.php
文件中启用插件
CakePlugin::load('Sanction');
如果您已经使用 CakePlugin::loadAll();
,则此步骤不是必需的。
使用
PermitComponent 设置
将 SanctionPlugin 安装在 app/Plugin/
目录下的 Sanction
文件夹中。
如果您想使用 PermitComponent
阻止用户访问控制器/操作,请将以下内容添加到您的 AppController
或特定控制器中
/**
* the 'path' key defines the Session key which holds user information (default Auth.User)
* the 'check' key defined the subfield of the path, used to verify only that someone is logged in (default: id)
*/
// Example for default AuthComponent Configuration (with associated models)
public $components = array('Sanction.Permit' => array(
'path' => 'Auth',
'check' => 'Auth.id'
));
// Example for default AuthComponent Configuration (no associated models, restricted to just looking at the User model)
public $components = array('Sanction.Permit' => array(
'path' => 'Auth.User'
));
// Example for default AuthsomeComponent Configuration (with associated models)
public $components = array('Sanction.Permit' => array(
'path' => 'User',
'check' => 'User.id'
));
// Example for default AuthsomeComponent Configuration (no associated models, restricted to just looking at the User model)
public $components = array('Sanction.Permit' => array(
'path' => 'User.User'
));
// Example for customized AuthsomeComponent Configuration (with associated models)
public $components = array(
'Authsome.Authsome' => array(
'model' => 'Member',
'configureKey' => 'MemberAuth',
'sessionKey' => 'MemberAuth',
'cookieKey' => 'MemberAuth',
),
'Sanction.Permit' => array('path' => 'MemberAuth')
);
// NOTE: you can also configure the settings in the permit.php file (below) in which case, just include the component by itself (this way the configuration is available to the debug_kit panel)
public $components = array('Sanction.Permit');
然后您将需要设置一些权限...
在您的 app/Config/
文件夹中创建一个名为 permit.php
的文件。您需要进行以下操作
- 添加
App::uses('Permit', 'Sanction.Controller/Component');
- 定义一些规则 - 这些规则将在下面概述 - 使用
Permit::access();
您可以通过浏览到您要保护的 URL 来测试这些规则。
ClearanceHelper 设置
将 SanctionPlugin 安装在 app/Plugin/
目录下的 Sanction
文件夹中。
如果您想使用 ClearanceHelper 阻止用户访问控制器/操作,请将以下内容添加到您的 AppController 或特定控制器中
// Example (use the same {{$PATH}} as in the component)
var $helpers = array('Sanction.Clearance' => array('path' => '{{$PATH}}'));
然后您将需要设置一些权限...
在您的 app/Config/
文件夹中创建一个名为 permit.php
的文件。您需要进行以下操作
- 添加
App::uses('Permit', 'Sanction.Controller/Component');
- 定义一些规则(这些规则将在下面概述)
然后,在您的视图中使用 $this->Clearance->link()
代替 $this->Html->link()
创建链接。如果当前登录的用户(或未登录用户)根据 app/config/permit.php
文件中定义的权限有权访问,则链接将出现在 ClearanceHelper 创建的任何视图中。
请注意,与 app/Config/permit.php
文件进行比较是一个昂贵的操作(目前是这样的!),因此您可能希望仅在将实际显示给不同用户的链接上使用此功能,而不是在应用程序中的所有链接上。
DebugKit 面板
在制裁插件中包含了一个debug_kit
面板(自提交fb061e57起),它不仅显示当前匹配的访问规则,还显示为应用程序定义的所有规则。如果您只想查看当前请求是否通过了规则,这将非常有用。
要使用它,请将以下内容添加到您的AppController中
// Example of how to implement the Sanction pannel
var $components = array(
'DebugKit.Toolbar' => array('panels' => array('Sanction.permit')),
);
将来,它还会保留过去请求的历史记录,并突出显示显式使用的访问规则。
规则
规则通过Permit::access();
定义,可以包含3个数组
- 我们将控制访问的规则数组。它可以是一个字符串,但这些选项不太灵活。
- 由用户会话定义的规则数组
- 如果您限制为单个模型且不使用关联数据,则可以仅输入Auth数组中要匹配的字段名
- 如果您使用关联模型,则需要指定一个
Set::extract()
路径作为字段名
- 额外参数数组,例如重定向位置、闪存消息等。
一个示例app/Config/permit.php
App::uses('Permit', 'Sanction.Controller/Component');
// no associated model, example: looks for $sessionUser['group'] == 'admin'
Permit::access(
array('controller' => 'posts', 'action' => array('add', 'edit', 'delete')),
array('auth' => array('group' => 'admin')),
array('redirect' => array('controller' => 'users', 'action' => 'login'))
);
// with associated model, example: looks for in_array('admin', Set::extract('/Group/name',$sessionUser))
Permit::access(
array('controller' => 'posts', 'action' => array('add', 'edit', 'delete')),
array('auth' => array('Group.name' => 'admin')),
array('redirect' => array('controller' => 'users', 'action' => 'login'))
);
对于上述内容,以下操作将受到影响
/posts/add/*
/posts/edit/*
/posts/delete/*
用户必须属于admin
组(第一个示例作为用户模型上的字段,第二个作为关联的Group模型),如果不是,则将被重定向到/users/login
。
App::uses('Permit', 'Sanction.Controller/Component');
// no associated model, example: looks for $sessionUser['group'] == 'admin'
Permit::access(
array('controller' => 'comments', 'action' => array('edit', 'delete')),
array('auth' => array('group' => 'admin')),
array(
'element' => 'comment',
'key' => 'flash',
'message' => __('You must be logged in to comment', true),
'redirect' => array('controller' => 'users', 'action' => 'login')
)
);
对于上述内容,以下操作将受到影响
/comments/edit/*
/comments/delete/*
用户必须有一个值为admin
的'group'字段,如果不是,则将被重定向到/users/login
。还将显示一个使用comment
元素的闪存消息,其中包含消息'您必须登录才能评论
'。
App::uses('Permit', 'Sanction.Controller/Component');
Permit::access(
array('controller' => array('comments'), 'action' => array('add')),
array('auth' => true),
array(
'message' => __('You must be logged in to comment', true),
'redirect' => array('controller' => 'users', 'action' => 'login')
)
);
对于上述内容,以下操作将受到影响
/comments/add/*
用户必须已认证,如果不是,则将被重定向到/users/login
。还会向他们展示一个包含消息'您必须登录才能评论
'的闪存消息。
App::uses('Permit', 'Sanction.Controller/Component');
// no associated model, example: looks for $sessionUser['group'] == 'admin'
Permit::access(
array('prefix' => 'admin'),
array('auth' => array('group' => 'admin')),
array('redirect' => array('admin' => false, 'controller' => 'users', 'action' => 'login')));
// with associated model, example: looks for in_array('admin', Set::extract('/Group/name',$sessionUser))
Permit::access(
array('prefix' => 'admin'),
array('auth' => array('Group.name' => 'admin')),
array('redirect' => array('admin' => false, 'controller' => 'users', 'action' => 'login'))
);
对于上述内容,任何具有admin前缀的路由都会受到影响。
用户必须属于admin
组,如果不是,则将被重定向到/users/login
。
您还可以使用字符串来引用URL而不是路由
App::uses('Permit', 'Sanction.Controller/Component');
Permit::access(
'/posts',
array('auth' => array('group' => 'admin')),
array('redirect' => array('controller' => 'users', 'action' => 'login'))
);
上述规则将仅影响对/posts
和/posts/
的请求;对/posts/index
或/posts/add
的请求将保持不变。为了规范目的,从规则中删除了尾随逗号。
您也可以指定查询字符串,但同样,它是一个字面匹配
App::uses('Permit', 'Sanction.Controller/Component');
Permit::access(
'/posts?page=5',
array('auth' => array('group' => 'admin')),
array('redirect' => array('controller' => 'users', 'action' => 'login'))
);
上述规则将仅影响/posts?page=5
,对/posts?page=6
或/posts?page=5&order=created
的请求在规则解析中将不予考虑。请在使用基于字符串的权限访问时注意这一点。
规则特定性
与路由一样,所有规则必须按照最具体到最不具体的顺序指定。以下两个示例将说明这一点
// If this access declaration comes first, this will be the
// ONLY declaration that Sanction uses. Once this fails,
// Sanction will not continue on to other rules
Permit::access(
array('controller' => array('posts', 'categories', 'comments'),
array('auth' => array('User.role' => array('admin'))),
array('redirect' => array('controller' => 'users', 'action' => 'account')
);
// So this declaration will be effectively useless.
Permit::access(
array('controller' => array('posts'), 'action' => array('edit'),
array('auth' => array('User.role' => array('manager', 'admin'))),
array('redirect' => array('controller' => 'users', 'action' => 'account')
);
为了指定规则,以便管理员用户可以编辑帖子,则需要切换规则。最限制性规则——即限制控制器和动作的规则,而不是仅限制控制器——应首先指定。以下将按预期工作
Permit::access(
array('controller' => array('posts'), 'action' => array('edit'),
array('auth' => array('User.role' => array('manager', 'admin'))),
array('redirect' => array('controller' => 'users', 'action' => 'account')
);
Permit::access(
array('controller' => array('posts', 'configs', 'comments'),
array('auth' => array('User.role' => array('admin'))),
array('redirect' => array('controller' => 'users', 'action' => 'account')
);
示例规则
允许匿名访问
Permit::access(
array('controller' => array('posts'), 'action' => array('index')),
array(),
array()
);
允许访问多个角色
Permit::access(
array('controller' => array('posts'), 'action' => array('add', 'delete')),
array('auth' => array('User.role' => array('user', 'admin'))),
array('redirect' => array('controller' => 'posts', 'action' => 'index'),
'message' => 'You are not authorized to perform the requested action.'
)
);
PermitBehavour设置
制裁现在包含一个行为,允许您拒绝访问其他用户拥有的记录,这主要是为了限制对edit()
动作的访问。它通过检查当前模型中指定的字段(默认为user_id
)与当前登录用户ID是否匹配来实现,如果不匹配,则抛出UnauthorizedException
。
要启用此功能,请将以下之一添加到您的模型中
// default set-up
public $actsAs = array(
'Sanction.Permit'
);
// example set-up with all available options, set your own defaults
public $actsAs = array(
'Sanction.Permit' => array(
'message' => 'You do not have permission to edit this post', // (string, optional) A message to display to the user when they do not have access to the model record. DEFAULTS TO: "You do not have permission to view this %ModelAlias%"
'field' => 'Post.user_id', // (string, optional) A `Hash::get()`-compatible string for retrieving the from the current record user_id. DEFAULTS TO: %ModelAlias%.user_id
'check' => 'is_admin', // (string, optional) optional admin override for returning the results when the user_id does not match the current user. DEFAULTS TO: false
'value' => true, // (mixed, optional) The value the check should resolve to. DEFAULTS TO: true
'skip' => true, // (boolean, optional) Whether to skip rule checking. DEFAULTS TO: true
'rules' => array(), (array, optional) If `permit` is set in a `Model::find()`, this key will be used to make an index lookup for rules to apply to this find. DEFAULTS TO: empty array
)
);
如果您想为单个数据检索调用添加额外的设置,有几个方法可以实现这一点
// passing additional settings via a `find('first')`
$params = array(
'conditions' => array('id' => $id),
'permit_skip' => false,
'permit_check' => 'is_admin',
'permit_value' => true,
);
$data = $this->find('first', $params);
// using the `permit()` method on the model
$this->permit(array(
'skip' => false,
'check' => 'is_admin',
'value' => true,
'persist' => true // (boolean, optional) if set to true, all settings passed here will persist for future `find()` requests, unless false is set
));
$this->request->data = $this->read(null, $id);
待办事项
- 更多单元测试
- 支持yaml/db-backed Permit Component权限加载
许可证
MIT许可证(MIT)
版权所有(c)2010 Jose Diaz-Gonzalez
特此授予任何人免费获得此软件及其相关文档副本(以下简称“软件”)的权利,不受限制地使用、复制、修改、合并、发布、分发、许可和/或出售软件副本,并允许将软件提供给他人以便他们进行此类操作,但需遵守以下条件
上述版权声明和本许可声明应包含在软件的所有副本或主要部分中。
软件按“原样”提供,不提供任何形式的保证,明示或暗示,包括但不限于适销性、针对特定目的的适用性和非侵权性。在任何情况下,作者或版权持有人均不对任何索赔、损害或其他责任负责,无论源于合同行为、侵权或其他,与软件或软件的使用或其他方式相关。