Herramientas de usuario

Herramientas del sitio


cursos:yii2:roles

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 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:

<?php 
 if(Yii::$app->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');
      ...
  }  
}