Acl en CakePHP
Ejecute las
siguientes instrucciones SQL en la base de datos:
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
);
Preparativos para añadir autenticación
Ahora tenemos
una aplicación CRUD funcionamiento. Bake debe tener la configuración de todas
las relaciones que necesitamos, si no añadirlos en este momento. Hay algunas
otras piezas que necesitan ser añadido antes de que podamos añadir los
componentes Auth y Acl. Primero se debe agregar un inicio de sesión y cierre de sesión de acción
para su UsersController:
public function login() {
if ($this->request->is('post')) {
if ($this->Auth->login()) {
return $this->redirect($this->Auth->redirectUrl());
}
$this->Session->setFlash(__('Your username or password was incorrect.'));
}
}
public function logout() {
//Leave empty for now.
}
A continuación,
cree el archivo de vista siguiente de inicio de sesión en app /view/users/login.ctp:
<?php
echo $this->Form->create('User', array('action' => 'login'));
echo $this->Form->inputs(array(
'legend' => __('Login'),
'username',
'password'
));
echo $this->Form->end('Login');
?>
El almacenamiento de contraseñas en texto
plano es extremadamente inseguro y AuthComponent esperará que sus contraseñas
se hash. En app/model/user.php añadir lo
siguiente:
App::uses('AuthComponent', 'Controller/Component');
class User extends AppModel {
// other code.
public function beforeSave($options = array()) {
$this->data['User']['password'] = AuthComponent::password(
$this->data['User']['password']
);
return true;
}
}
Como queremos todo nuestro sitio controlado con autenticación y ACL, vamos
a ponerlos en AppController:
class AppController extends Controller {
public $components = array(
'Acl',
'Auth' => array(
'authorize' => array(
'Actions' => array('actionPath' => 'controllers')
)
),
'Session'
);
public $helpers = array('Html', 'Form', 'Session');
public function beforeFilter() {
//Configure AuthComponent
$this->Auth->loginAction = array(
'controller' => 'users',
'action' => 'login'
);
$this->Auth->logoutRedirect = array(
'controller' => 'users',
'action' => 'login'
);
$this->Auth->loginRedirect = array(
'controller' => 'posts',
'action' => 'add'
);
}
}
Antes de
configurar la ACL del todo tendremos que añadir algunos usuarios y grupos. Con AuthComponent en uso no vamos a ser capaces de acceder a cualquiera de nuestras acciones,
ya que no se ha identificado. Ahora vamos a añadir algunas excepciones para AuthComponent nos permitirá crear algunos grupos y usuarios. En tanto su GroupsController y su UsersController Añadir el siguiente:
public function beforeFilter() {
parent::beforeFilter();
// For CakePHP 2.0
$this->Auth->allow('*');
// For CakePHP 2.1 and up
$this->Auth->allow();
}
Estas declaraciones dicen AuthComponent
para permitir el acceso público a todas las acciones. Esto es sólo
temporal y se eliminará una vez que tengamos unos usuarios y grupos en nuestra
base de datos. No agregue los usuarios o grupos por el momento sin embargo.
Inicializar las tablas Acl Db
Antes de crear los usuarios o grupos
querremos conectarlos con el Acl. Sin embargo, no tenemos en este momento
tenemos ninguna tabla Acl y si intenta ver las páginas en este momento,
obtendremos un error de tabla que falta ("Error: No se encontró acos tabla
de base de datos para el modelo de Aco."). Para eliminar estos errores necesitamos
ejecutar:
$ cake schema create DbAcl
Este esquema le pedirá que deje caer y crear las tablas. Acepta la eliminación y la creación de las tablas.
Si usted no tiene acceso a una consola, o
tiene algún problema usando la consola, puede ejecutar el archivo sql
encontrado en /app/Config/Schema/db_acl.sql.
Actúa como un Solicitante
Para
autenticación y Acl funcionen correctamente tenemos que asociar nuestros
usuarios y grupos a filas en las tablas de ACL. Para hacer esto usaremos el AclBehavior. El AclBehavior permite la conexión automagic de modelos con las tablas Acl. Su uso requiere
una implementación de parentNode() en su modelo. En nuestra modelo User añadiremos lo siguiente:
class User extends AppModel {
public $belongsTo = array('Group');
public $actsAs = array('Acl' => array('type' => 'requester'));
public function parentNode() {
if (!$this->id && empty($this->data)) {
return null;
}
if (isset($this->data['User']['group_id'])) {
$groupId = $this->data['User']['group_id'];
} else {
$groupId = $this->field('group_id');
}
if (!$groupId) {
return null;
}
return array('Group' => array('id' => $groupId));
}
}
Luego, en
nuestro modelo Group agregue:
class Group extends AppModel {
public $actsAs = array('Acl' => array('type' => 'requester'));
public function parentNode() {
return null;
}
}
¿Qué hace esto,
está vinculada al Grupo y usuario modelos a la
ACL, y decirle a CakePHP que cada vez que haga un usuario o grupo que desee una
entrada en la tabla aros también.
ACL-único grupo
En caso de que
queramos simplificados sólo permisos por grupo, tenemos que poner en práctica bindNode() en el modelo user:
public function bindNode($user) {
return array('model' => 'Group', 'foreign_key' => $user['User']['group_id']);
}
A continuación,
modifique los actsAs para el modelo user y desactivar la directiva solicitante:
public $actsAs = array('Acl' => array('type' => 'requester', 'enabled' => false));
Nota: Cada usuario tiene que haber group_id asignado para que esto funcione.
Ahora el aros tabla se verá así:
+----+-----------+-------+-------------+-------+------+------+
| id | parent_id | model | foreign_key | alias | lft | rght |
+----+-----------+-------+-------------+-------+------+------+
| 1 | NULL | Group | 1 | NULL | 1 | 2 |
| 2 | NULL | Group | 2 | NULL | 3 | 4 |
| 3 | NULL | Group | 3 | NULL | 5 | 6 |
+----+-----------+-------+-------------+-------+------+------+
3 rows in set (0.00 sec)
Creación de ACO (Access Control Objects)
Ahora que tenemos nuestros usuarios y
grupos (aros), podemos empezar a ingresar nuestros controladores en el Acl y
fijar los permisos para nuestros grupos y usuarios, así como permitir login /
logout.
Nuestra ARO
están creando automáticamente a sí mismos cuando se crean nuevos usuarios y
grupos. ¿Qué pasa con una forma de auto-generar ACO desde nuestros controladores y
sus acciones? Bueno, lamentablemente no hay forma mágica en el núcleo de CakePHP para
lograr esto. Las clases del núcleo ofrecen unas pocas formas de crear manualmente pesar
de ACO. Puede crear objetos ACO de la cáscara Acl o Puede utilizar la AclComponent.
$ cake acl create aco root controllers
Si bien desde el AclComponent se verá como:
$this->Acl->Aco->create(array('parent_id' => null, 'alias' => 'controllers'));
$this->Acl->Aco->save();
Ambos ejemplos crearía
nuestra 'root' o nivel superior ACO que va a ser llamado 'controladores'. El propósito de
este nodo raíz es para hacer más fácil para permitir / denegar el acceso en un
ámbito de aplicación mundial, y permitir el uso del Acl para fines no relacionados
con los controladores / acciones como la comprobación de permisos de registro
del modelo.
Como vamos a utilizar un ACO raíz global tenemos que hacer una pequeña modificación en nuestro AuthComponent configuración. AuthComponent necesita saber acerca de la existencia de este nodo raíz, por lo que al hacer ACL comprueba que puede utilizar la ruta de nodo correcto al buscar controladores / acciones. En AppController asegurar que su componentes $ array contiene el actionPath definido anteriormente:
Como vamos a utilizar un ACO raíz global tenemos que hacer una pequeña modificación en nuestro AuthComponent configuración. AuthComponent necesita saber acerca de la existencia de este nodo raíz, por lo que al hacer ACL comprueba que puede utilizar la ruta de nodo correcto al buscar controladores / acciones. En AppController asegurar que su componentes $ array contiene el actionPath definido anteriormente:
class AppController extends Controller {
public $components = array(
'Acl',
'Auth' => array(
'authorize' => array(
'Actions' => array('actionPath' => 'controllers')
)
),
'Session'
);
Sencilla aplicación controlada Acl - parte 2
Una herramienta automática para crear ACOs
Como se mencionó antes, no hay manera de pre-construidos a
la entrada de todos nuestros controladores y acciones en la ACL. Sin embargo, todos odiamos hacer cosas
repetitivas como escribir en lo que podría haber cientos de acciones en una
aplicación grande.
Para ello existe un plugin muy útil
disponible en GitHub, llamado AclExtras que se puede descargar en la página de GitHub Descargas. Vamos
a describir brevemente cómo utilizarla para generar toda nuestra ACO de
En primer lugar tomar una copia del
plugin y descomprimido o clonar usando git en app/Plugins/AclExtras. Luego activar el plugin como se muestra a
continuación:
//app/Config/boostrap.php
// ...
CakePlugin::load('AclExtras');
Configuración de permisos
A fin de permitir a la AclComponent usaríamos
la siguiente sintaxis de código en un método personalizado:
$this->Acl->allow($aroAlias, $acoAlias);
Agregue lo siguiente a una función temporal en su UsersController
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('initDB'); // We can remove this line after we're finished
}
public 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');
// allow basic users to log out
$this->Acl->allow($group, 'controllers/users/logout');
// we add an exit to avoid an ugly "missing views" error message
echo "all done";
exit;
}
Ahora hemos establecido algunas reglas básicas de acceso. Hemos permitido que los administradores
a todo. Los administradores
pueden acceder a todo en los puestos y widgets. Mientras que los usuarios sólo pueden
acceder a añadir y editar en los puestos y widgets.
Iniciar sesión
Agregue lo siguiente a app /View/Users/login.ctp si no lo ha hecho:
<h2>Login</h2>
<?php
echo $this->Form->create('User', array(
'url' => array(
'controller' => 'users',
'action' => 'login'
)
));
echo $this->Form->input('User.username');
echo $this->Form->input('User.password');
echo $this->Form->end('Login');
Si un usuario ya está conectado, le redirigir añadiendo esto
a su UsersController:
public function login() {
if ($this->Session->read('Auth.User')) {
$this->Session->setFlash('You are logged in!');
return $this->redirect('/');
}
}
Ahora debería ser capaz de iniciar
sesión y todo debe trabajar auto-mágicamente. Cuando
se mostrarán Acceso denegado mensajes Auth si se ha añadido la echo $
this-> Session-> flash ('auth')
Cerrar sesion
Ahora sobre el cierre de sesión. Más temprano salimos de esta función
en blanco, ahora es el momento para llenarlo. En UsersController
:: logout () añade lo siguiente:
$this->Session->setFlash('Good-Bye');
$this->redirect($this->Auth->logout());
Esto establece un mensaje flash de sesión y cierra la sesión
del usuario, utilizando el método de cierre de sesión de autenticación. Método de cierre de sesión de
autenticación básicamente elimina la clave de sesión de autenticación y
devuelve un URL que se puede utilizar en una redirección. Si hay otros datos de sesión que
necesita ser eliminado, así que añadir código aquí.
Todo listo
Ahora debería tener una aplicación controlada por autenticación
y ACL. Usuarios permisos se
establecen a nivel de grupo, pero puede ponerlos por el usuario a la vez. También puede establecer permisos en
una global y per-controlador y por acción base. Además, tiene un bloque reutilizable
de código para ampliar fácilmente su mesa ACO como su aplicación crece.
Comentarios
Publicar un comentario