josegonzalez/cakephp-sanction

使用 Sanction 插件将所有权限集中在一个文件中。

安装: 178

依赖项: 0

建议者: 0

安全: 0

星标: 32

关注者: 4

分支: 9

公开问题: 0

类型:cakephp-plugin

2.1.0 2014-04-13 10:13 UTC

This package is auto-updated.

Last update: 2024-08-29 04:14:22 UTC


README

Build Status Coverage Status Total Downloads Latest Stable Version Documentation Status Gratipay

用于 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 文件中。(为什么? 阅读此内容。)

[手动]

[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

特此授予任何人免费获得此软件及其相关文档副本(以下简称“软件”)的权利,不受限制地使用、复制、修改、合并、发布、分发、许可和/或出售软件副本,并允许将软件提供给他人以便他们进行此类操作,但需遵守以下条件

上述版权声明和本许可声明应包含在软件的所有副本或主要部分中。

软件按“原样”提供,不提供任何形式的保证,明示或暗示,包括但不限于适销性、针对特定目的的适用性和非侵权性。在任何情况下,作者或版权持有人均不对任何索赔、损害或其他责任负责,无论源于合同行为、侵权或其他,与软件或软件的使用或其他方式相关。