===== Seguridad. Autorización de acciones =====
Yii implementa dos métodos de autorización de acciones. Uno básico, válido para aplicaciones que únicamente necesiten controlar el acceso en función de si un usuario está logueado o no, o tiene un perfil determinado (administrador, usuario, etc...). En [[http://www.yiiframework.com/doc-2.0/guide-security-authorization.html|este enlace]] puedes consultar los detalles.
Aquí explicaremos cómo utilizar el método sencillo (ACF), usando una propiedad del usuario logueado que indica el rol o roles asignados.
Imaginemos que en nuestra aplicación tenemos dos roles de usuario: el de administrador, que tiene permisos para gestionar toda la aplicación y el de usuario que tiene limitados determinados accesos. Por ejemplo: el administrador puede crear, modificar, borrar y listar usuarios, pero un usuario normal solamente puede ver su ficha de usuario y modificarla.
=== Cambios en el Modelo ===
En el modelo usuario necesitamos un atributo **rol (o roles)**. Este atributo puede ser:
* Un campo de la tabla usuarios, donde guardaremos, por ejemplo: A si es administrador o U si es usario normal
* Una relación con otro modelos (roles), que me devuelve una lista de roles admitidos para el usuario
En cualquiera de los dos casos, tenemos una propiedad roles (string o array) que me dice qué roles tiene el usuario. Por comodidad, crearemos un método llamado hasRole($rol) que devolverá true cuando el usuario tenga ese rol asignado:
class Usuarios extends ActiveRecord {
...
function hasRole($role){
return $this->rol==$role;
//return in_array($this->roles,$role); Si es un array de roles
}
...
}
Simplemente con esto, ya podemos utilizar en nuestras vistas y controladores el chequeo de un rol, ya que Yii::$app->user->identity se corresponde con el modelo del usuario logueado, y podemos llamar al método que acabamos de crear para verificar si el usuario tiene un rol asignado
=== Chequeo del rol en vistas ===
Por ejemplo, si queremos que un botón en una vista aparezca solamente para los administradores:
user->identity->hasRole('A')
echo Html::a('Anular Pedido',['pedidos/enviar','id'=>$id]);
Tal como se explica en la guia de Yii, en el controlador definiremos el valor de 'access' en el método behaviors, asociándolo a la clase AccessControl, y haremos una entrada por cada filtro que queramos poner.
=== Autorización de acciones en los controladores ===
Tal como se explica en el documento del enlace de arriba, utilizaremos la propiedad matchCallBack de AccessControl, definida en el método behaviors. Por ejemplo, para que la acción create y delete deUsuarios únicamente la pueda ejecutar un administrador, pero la acción update la puedan ejecutar los usuarios que estén logueados y situación de alta (estado ='A') :
class UsuariosController extends Controller
{
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['create','delete','update'],
'rules' => [
['allow' => true,
'actions' => ['create', 'delete'],
'matchCallback' => function ($rule, $action) {
return Yii::$app->user->identity->hasRole('A');
}
],
['allow' => true,
'actions' => ['update'],
'matchCallback' => function ($rule, $action) {
return !Yii::$app->user->isGuest &&
Yii::$app->user->identity->estado=="A"; //Un usuario identificado y de alta
}
],
],
],
];
}
// ...
}
Es habitual que determinadas acciones solamente se puedan ejecutar en función del valor de determinadas propiedades del modelo. Por ejemplo: la acción update en el caso anterior es utilizable por un usuario, pero solamente para sí mismo. O un pedido solamente se puede borrar si no ha sido enviado. Este tipo de filtros los pondremos en la acción del controlador:
class UsuariosController extends Controller {
...
public function actionUpate($id) {
$user=Yii::$app->user->identity;
if(!$user->hasRole("A") && $id!=$user->id) //Si el usuario no es administrador solamente puede acceder a sus datos
throw new UnauthorizedHttpException('Acceso no permitido');
...
}
}