- 浏览: 50463 次
- 性别:
- 来自: 深圳
最新评论
自学习cakephp
以来,一直没有完成搞懂acl,也查过了很多资料,但对它的用法也是一知半解,acl应该是cakephp中一个比较难懂的地方,这几天又重新看了下手册,发现acl没有相信中的难,但比我想象中的好用.欢迎大家转载和访问我的网站http://www.batterylaptops.co.uk
下面让我说说它的具体用法已经使用过程中应该注意到问题
准备前工作:
最好是能配置好bake,使bake命名有效,虽然这个不是必须的,不过有这个命令行工具以后我们会方便很多
在你的数据库
中导入下面的sql语句
- CREATE TABLE users (
- id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
- username VARCHAR(255) NOT NULL UNIQUE,
- password CHAR(40) NOT NULL,
- group_id INT(11) NOT NULL,
- created DATETIME,
- modified DATETIME
- );
-
- CREATE TABLE groups (
- id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
- name VARCHAR(100) NOT NULL,
- created DATETIME,
- modified DATETIME
- );
- CREATE TABLE posts (
- id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
- user_id INT(11) NOT NULL,
- title VARCHAR(255) NOT NULL,
- body TEXT,
- created DATETIME,
- modified DATETIME
- );
- CREATE TABLE widgets (
- id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
- name VARCHAR(100) NOT NULL,
- part_no VARCHAR(12),
- quantity INT(11)
- );
在这里我们使用cake bake all命令工具快速生成models, controllers, 和 views(在这里我就详细介绍怎么使用cakephp中的bake命令了)
下一步,准备使用auth组件认证
首先我们打开users_controller.php在UsersController类中增加登录登出动作
- function login() {
- //Auth Magic
- }
-
- function logout() {
- //Leave empty for now.
- }
- 然后创建视图文件
app/views/users/login.ctp
- <?php
- $session->flash('auth');
- echo $form->create('User', array('action' => 'login'));
- echo $form->inputs(array(
- 'legend' => __('Login', true),
- 'username',
- 'password'
- ));
- echo $form->end('Login');
- ?>
下一步我们需要修改AppController(/app/app_controller.php),如果你的app目录下面没有app_controller.php文件的话,你可以自己创建一个
- <?php
- class AppController extends Controller {
- var $components = array('Acl', 'Auth');
- function beforeFilter() {
- //Configure AuthComponent
- $this->Auth->authorize = 'actions';
- $this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
- $this->Auth->logoutRedirect = array('controller' => 'users', 'action' => 'login');
- $this->Auth->loginRedirect = array('controller' => 'posts', 'action' => 'add');
- }
- }
- ?>
接下来我们需要修改GroupsController和UsersController,这两个文件的目录大家应该都知道在哪里吧..
在这两个控制器中分别添加以下代码
- function beforeFilter() {
- parent::beforeFilter();
- $this->Auth->allowedActions = array('*');
- }
其实这段代码的意思是允许用户访问所有user和group下的action,当然这个后面是要改回来的
接下来我们要初始化acl表
因为现在我们的数据
库中就只有四个表,还没有导入acl表
我们用下面语句导入acl表到数据库中
在命令行中输入cake schema run create DbAcl
我们根据提示导入表
接下来我们需要修改user和group模型
首先我们打开model目录下的user.php增加以下代码(事实上你可以用下面代码替换)
- var $name = 'User';
- var $belongsTo = array('Group');
- var $actsAs = array('Acl' => 'requester');
-
- function parentNode() {
- if (!$this->id && empty($this->data)) {
- return null;
- }
- $data = $this->data;
- if (empty($this->data)) {
- $data = $this->read();
- }
- if (!$data['User']['group_id']) {
- return null;
- } else {
- return array('Group' => array('id' => $data['User']['group_id']));
- }
- }
然后修改group模型
- var $actsAs = array('Acl' => array('requester'));
-
- function parentNode() {
- return null;
- }
好
了,到这一步我们需要暂时停一下了,现在在浏览器中打开相应的user和group页面,增加user和group,比如我的,我打开
http://localhost/cakephp/groups增加组,打开http://localhost/cakephp/users/
增加用户,在这里我们增加三个组和三个用户
添加完以后你可以打开phpmyadmin看下aros表看下是不是多了些记录
是不是觉得很神奇不可思议啊,哈哈,这就是框架的魅力,到目前为止和acl有关的表,就只有aros表中存在记录
在我们以后修改每一个user用户时,我们也必须修改aros表记录
所有我们应该做user模型中增加下面代码
- /**
- * After save callback
- *
- * Update the aro for the user.
- *
- * @access public
- * @return void
- */
- function afterSave($created) {
- if (!$created) {
- $parent = $this->parentNode();
- $parent = $this->node($parent);
- $node = $this->node();
- $aro = $node[0];
- $aro['Aro']['parent_id'] = $parent[0]['Aro']['id'];
- $this->Aro->save($aro);
- }
- }
到这里我们aro创建已经完成,接下来我们应该创佳aco了
我们应该知道其实acl的本质是用来定义一个ARO在什么时候可以访问一个aco的组件,明白了这一点一切就变的很简单了。
为了简单我们使用命令行执行cake acl create aco root controllers
你现在再用phpmyadmin打开acors表,你应该会看到表中已经有一条记录了,这条记录就是刚刚执行这个命令的结果,当然我们不一定非得用命令行工具的。
接下来我们还需要修改下AppController,在里面的beforeFilter方法中我们需要增加一行$this->Auth->actionPath = 'controllers/';
下面是重点,在我们的app项目中可能会存在很多的控制器和方法,我们需要把每个action都添加到acors表中来实现权限控制,当然如果你不怕麻烦的话可以一个一个手动添加,但我想大多数程序员还是很懒的,所有我们这里需要使用自动生成工具
这里我们添加下面代码放在users_controller.php中,当然你也可以放在其他的控制器中
下面我就在users_controller.php中增加下面代码
- function build_acl() {
- if (!Configure::read('debug')) {
- return $this->_stop();
- }
- $log = array();
- $aco =& $this->Acl->Aco;
- $root = $aco->node('controllers');
- if (!$root) {
- $aco->create(array('parent_id' => null, 'model' => null, 'alias' => 'controllers'));
- $root = $aco->save();
- $root['Aco']['id'] = $aco->id;
- $log[] = 'Created Aco node for controllers';
- } else {
- $root = $root[0];
- }
- App::import('Core', 'File');
- $Controllers = Configure::listObjects('controller');
- $appIndex = array_search('App', $Controllers);
- if ($appIndex !== false ) {
- unset($Controllers[$appIndex]);
- }
- $baseMethods = get_class_methods('Controller');
- $baseMethods[] = 'buildAcl';
- $Plugins = $this->_getPluginControllerNames();
- $Controllers = array_merge($Controllers, $Plugins);
- // look at each controller in app/controllers
- foreach ($Controllers as $ctrlName) {
- $methods = $this->_getClassMethods($this->_getPluginControllerPath($ctrlName));
- // Do all Plugins First
- if ($this->_isPlugin($ctrlName)){
- $pluginNode = $aco->node('controllers/'.$this->_getPluginName($ctrlName));
- if (!$pluginNode) {
-
$aco->create(array('parent_id' => $root['Aco']['id'], 'model'
=> null, 'alias' => $this->_getPluginName($ctrlName)));
- $pluginNode = $aco->save();
- $pluginNode['Aco']['id'] = $aco->id;
- $log[] = 'Created Aco node for ' . $this->_getPluginName($ctrlName) . ' Plugin';
- }
- }
- // find / make controller node
- $controllerNode = $aco->node('controllers/'.$ctrlName);
- if (!$controllerNode) {
- if ($this->_isPlugin($ctrlName)){
- $pluginNode = $aco->node('controllers/' . $this->_getPluginName($ctrlName));
-
$aco->create(array('parent_id' => $pluginNode['0']['Aco']['id'],
'model' => null, 'alias' =>
$this->_getPluginControllerName($ctrlName)));
- $controllerNode = $aco->save();
- $controllerNode['Aco']['id'] = $aco->id;
- $log[] = 'Created Aco
node for ' . $this->_getPluginControllerName($ctrlName) . ' ' .
$this->_getPluginName($ctrlName) . ' Plugin Controller';
- } else {
-
$aco->create(array('parent_id' => $root['Aco']['id'], 'model'
=> null, 'alias' => $ctrlName));
- $controllerNode = $aco->save();
- $controllerNode['Aco']['id'] = $aco->id;
- $log[] = 'Created Aco node for ' . $ctrlName;
- }
- } else {
- $controllerNode = $controllerNode[0];
- }
- //clean the methods. to remove those in Controller and private actions.
- foreach ($methods as $k => $method) {
- if (strpos($method, '_', 0) === 0) {
- unset($methods[$k]);
- continue;
- }
- if (in_array($method, $baseMethods)) {
- unset($methods[$k]);
- continue;
- }
- $methodNode = $aco->node('controllers/'.$ctrlName.'/'.$method);
- if (!$methodNode) {
-
$aco->create(array('parent_id' => $controllerNode['Aco']['id'],
'model' => null, 'alias' => $method));
- $methodNode = $aco->save();
- $log[] = 'Created Aco node for '. $method;
- }
- }
- }
- if(count($log)>0) {
- debug($log);
- }
- }
- function _getClassMethods($ctrlName = null) {
- App::import('Controller', $ctrlName);
- if (strlen(strstr($ctrlName, '.')) > 0) {
- // plugin's controller
- $num = strpos($ctrlName, '.');
- $ctrlName = substr($ctrlName, $num+1);
- }
- $ctrlclass = $ctrlName . 'Controller';
- $methods = get_class_methods($ctrlclass);
- // Add scaffold defaults if scaffolds are being used
- $properties = get_class_vars($ctrlclass);
- if (array_key_exists('scaffold',$properties)) {
- if($properties['scaffold'] == 'admin') {
- $methods =
array_merge($methods, array('admin_add', 'admin_edit', 'admin_index',
'admin_view', 'admin_delete'));
- } else {
- $methods = array_merge($methods, array('add', 'edit', 'index', 'view', 'delete'));
- }
- }
- return $methods;
- }
- function _isPlugin($ctrlName = null) {
- $arr = String::tokenize($ctrlName, '/');
- if (count($arr) > 1) {
- return true;
- } else {
- return false;
- }
- }
- function _getPluginControllerPath($ctrlName = null) {
- $arr = String::tokenize($ctrlName, '/');
- if (count($arr) == 2) {
- return $arr[0] . '.' . $arr[1];
- } else {
- return $arr[0];
- }
- }
- function _getPluginName($ctrlName = null) {
- $arr = String::tokenize($ctrlName, '/');
- if (count($arr) == 2) {
- return $arr[0];
- } else {
- return false;
- }
- }
- function _getPluginControllerName($ctrlName = null) {
- $arr = String::tokenize($ctrlName, '/');
- if (count($arr) == 2) {
- return $arr[1];
- } else {
- return false;
- }
- }
- /**
- * Get the names of the plugin controllers ...
- *
- * This function will get an array of the plugin controller names, and
- * also makes sure the controllers are available for us to get the
- * method names by doing an App::import for each plugin controller.
- *
- * @return array of plugin names.
- *
- */
- function _getPluginControllerNames() {
- App::import('Core', 'File', 'Folder');
- $paths = Configure::getInstance();
- $folder =& new Folder();
- $folder->cd(APP . 'plugins');
- // Get the list of plugins
- $Plugins = $folder->read();
- $Plugins = $Plugins[0];
- $arr = array();
- // Loop through the plugins
- foreach($Plugins as $pluginName) {
- // Change directory to the plugin
- $didCD = $folder->cd(APP . 'plugins'. DS . $pluginName . DS . 'controllers');
- // Get a list of the files that have a file name that ends
- // with controller.php
- $files = $folder->findRecursive('.*_controller\.php');
- // Loop through the controllers we found in the plugins directory
- foreach($files as $fileName) {
- // Get the base file name
- $file = basename($fileName);
- // Get the controller name
- $file = Inflector::camelize(substr($file, 0, strlen($file)-strlen('_controller.php')));
- if (!preg_match('/^'. Inflector::humanize($pluginName). 'App/', $file)) {
- if (!App::import('Controller', $pluginName.'.'.$file)) {
- debug('Error importing '.$file.' for plugin '.$pluginName);
- } else {
- /// Now prepend the Plugin name ...
- // This is required to allow us to fetch the method names.
- $arr[] = Inflector::humanize($pluginName) . "/" . $file;
- }
- }
- }
- }
- return $arr;
- }
增加好以后我们打开浏览器访问刚才的方法
比如我的http://localhost/cakephp/users/build_acl
运行后程序会自动把所有controller下的action都添加到acos表中,你现在打开acos表应该就会看到很多记录了,如
接下来应该是做我们最兴奋的事情了,就是实现权限控制,因为我们前期准备工作都做好了,最终我们都是为了实现可以控制权限
1. 先来介绍下语法,允许访问$this->Acl->allow($aroAlias, $acoAlias);
拒绝访问$this->Acl->deny($aroAlias, $acoAlias);
你先打开aros_acos表中看下,到目前为止该表应该还是没有记录的
我们可以写一个初始化函数
我同样把这段代码放在user控制器中
- function initDB() {
- $group =& $this->User->Group;
- //Allow admins to everything
- $group->id = 1;
- $this->Acl->allow($group, 'controllers');
-
- //allow managers to posts and widgets
- $group->id = 2;
- $this->Acl->deny($group, 'controllers');
- $this->Acl->allow($group, 'controllers/Posts');
- $this->Acl->allow($group, 'controllers/Widgets');
-
- //allow users to only add and edit on posts and widgets
- $group->id = 3;
- $this->Acl->deny($group, 'controllers');
- $this->Acl->allow($group, 'controllers/Posts/add');
- $this->Acl->allow($group, 'controllers/Posts/edit');
- $this->Acl->allow($group, 'controllers/Widgets/add');
- $this->Acl->allow($group, 'controllers/Widgets/edit');
- }
接下来我们在浏览器中访问这个action
这个是时候你就应该发现你的aros_acos表中多了很多条记录,哈哈,这个就是acl的秘密所在.
接下来你可以使用不同组的用户名登录访问,你还可以修改initDB里面的代码进行测试,至于实际工作中如何使用,那就要看你自己的了,最后祝大家工作愉快!最后我把文档放在这里,有兴趣的朋友可以下载
cakephp中acl详解.rar
转载自: Batterylaptops
相关推荐
在CakePHP中,ACL由三个主要部分组成:Aro(Access Request Object),Aco(Access Control Object)和Ace(Access Control Entry)。Aro代表请求访问的主体,如用户或角色;Aco代表可被访问的客体,如控制器、动作...
在CakePHP中,Access Control List(ACL)是一个强大的工具,用于管理应用程序中的权限和访问控制。让我们深入探讨一下CakePHP中的ACL系统。 ### ACL基础概念 **1. ACO (Access Control Object)**:ACO代表要控制...
cakephp-jwt-auth, 使用JSON网络令牌进行身份验证的CakePHP插件 CakePHP认证插件 包含AuthComponent类认证的插件,用于使用 JSON网络令牌进行身份验证。 你可以在这里详细阅读关于JSON网络令牌规范的详细说明。要求...
composer require admad/cakephp-jwt-auth 用法 使用Cake的控制台加载插件: ./bin/cake plugin load ADmad/JwtAuth 配置: 设置AuthComponent : // In your controller, for e.g. src/Api/AppController.php ...
在CakePHP中,视图可以包含HTML、CSS和JavaScript,也可以包含其他的视图元素,如小部件和布局,以构建复杂的用户界面。 5. **控制器(Controller)**: 控制器处理用户的请求,调用模型并填充视图所需的数据。它...
**蛋糕PHP(CakePHP)框架详解** 蛋糕PHP(CakePHP)是一个基于模型-视图-控制器(MVC)模式的开源PHP框架,旨在简化Web应用的开发过程,提高开发效率。这个“cakephp 中文手册”是专为中文开发者设计的,提供了...
本手册是针对CakePHP的中文版指南,对于学习和理解这个框架的中文使用者来说,是一份极其宝贵的资源。 在 CakePHP 中,开发者可以快速地搭建功能丰富的Web应用程序。其主要特点包括: 1. **快速开发**:CakePHP ...
CakePHP 1.2 API 中文文档是针对这个版本的详细技术参考,为开发者提供了丰富的接口信息和使用指南,特别适合那些不熟悉英文文档或希望快速查找中文资料的开发者。 **MVC架构介绍** 在 CakePHP 中,MVC模式是核心...
### CakePHP 中文文档知识点详解 #### 一、CakePHP 的基本原则 CakePHP 是一款基于 PHP 的开源快速开发框架,采用 MVC(Model-View-Controller)设计模式,旨在提高开发效率的同时保持代码的清晰性和可维护性。其...
本文将详细介绍CakePHP 2.0中的一项新特性——Request和Response对象,帮助初学者更好地掌握这些核心组件。 #### 二、CakePHP中的Request和Response对象概述 在CakePHP 2.0之前,请求和响应信息通常通过数组传递,...
CakePHP无状态AuthComponent 完全和严格无状态的替代CakePHP身份验证/授权组件。 设计用于仅通过REST访问的Cake应用程序。 提供的组件旨在替代Cake的库存AuthCompnent 。 此替代StatelessAuthComponent是经过精简和...
在 CakePHP 中,MVC模式被实现得非常直观和易于使用。例如,控制器类通常放在`app/Controller`目录下,模型类位于`app/Model`,而视图文件则位于`app/View`。 **MVC 模式** 虽然手册建议在阅读前了解MVC的基本概念...
CakePHP有多个特点,这些特点让CakePHP成为了快速开发框架中的佼佼者之一。 1.活跃友好的社区 2.灵活的许可协议(Licensing) 3.兼容PHP4和PHP5 4.数据库交互和简单查询的集成 5.应用程序Scaffolding 6....
1. 插件:提供可复用的代码库,如Auth用于身份验证,Acl处理权限控制。 2. 组件:类似PHP的类,封装通用功能,如RequestHandler处理HTTP请求类型。 总结,CakePHP 1.3.21是一个功能丰富的PHP框架,通过遵循MVC架构...
权限控制可能通过 CakePHP 的ACL(Access Control List)组件来实现,允许管理员设定不同用户对相册和照片的操作权限。 在开发过程中,CakePHP 的 Bake 工具可以自动生成CRUD(创建、读取、更新、删除)操作的控制...
CakePHP中文手册作为开发者的重要参考资料,包含了全面的API文档、教程、最佳实践以及常见问题解答,帮助开发者更好地理解和运用CakePHP。 在**中文手册**中,你将找到以下关键知识点: 1. **安装与配置**:包括...
标题中的“mvc,mvc手册cakephp中文手册”表明这是一个关于Model-View-Controller(MVC)架构模式的资源,特别是针对CakePHP框架的中文手册。描述部分的重复强调了这一点,暗示这个压缩包可能包含一份详尽的、面向...
- **异常**:探讨了异常处理的最佳实践,以及如何在CakePHP中捕获和处理异常。 - **错误处理**:提供了错误处理的策略,以及如何定制错误页面。 - **调试**:介绍了CakePHP提供的调试工具和技巧。 - **测试**:讲解...