Posts etiquetados ‘php’

Desde hace algún tiempo he comprobado que hay muchos desarrolladores que al tratar de implementar un sistema de autenticación en CakePHP con AuthComponent tienen problemas y no funciona como debería. Sea por motivos de versión del framework o, simplemente, porque no está bien implementado el código, la cuestión es que la aplicación no funciona.
Vamos entonces a ver a continuación cómo programar un sistema de autenticación sin la necesidad del AuthComponent.
Partimos de que tenemos una base de datos conectada correctamente a través de la configuración de nuestro archivo database.php y, además, suponemos que tenemos ya una aplicación en CakePHP que debemos proteger de usuarios no autenticados.
Con lo primero que debemos contar es con una tabla en nuestra base de datos que yo he llamado users. Esta tabla cuenta a su vez con tres campos: id, username y password. El campo id será nuestra clave primaria autoincremental y los otros dos campos de tipo varchar.
Una vez hecho esto, vamos con el código. Abrimos nuestro archivo AppController que se encuentra en la ruta CarpetaAplicacion/app/Controller donde CarpetaAplicacion es el nombre de la carpeta donde guardas tu proyecto. Escribimos el siguiente código:

<?php

App::uses('Controller','Controller');

class AppController extends Controller {

public$components=array('Session');

    // Comprobar si el usuario está logueado
    function authenticate()
    {
        // Comprobamos si la variable de sesión existe. Si es así quiere decir que el usuario se ha logueado
       //correctamente y se le redirecciona a la aplicación.
      //Si no existe se le devuelve al login.
        if(!$this->Session->check('User'))
        {
            $this->redirect(array('controller'=>'users','action'=>'autenticar'));
            exit();
        }

    }
 
    //Autenticación obligatoria si se quiere entrar a cualquier parte de la aplicación
    function afterFilter()
    {
        if($this->action!='autenticar')
        {
            $this->authenticate();
        }
    }
}

La función afterFilter va a permitirnos controlar cuándo un usuario intenta entrar en una zona donde se ejecuta una acción distinta a ‘autenticar’. Inmediatamente llama a la función authenticate que nos va a permitir saber si se ha creado ya una sesión de usuario. Si es así significará que el usuario esta autenticado, con lo que automáticamente será redireccionado al index de la aplicación. Si no es así se le redireccionará de nuevo a la acción autenticar del controlador users (lo veremos a continuación) que, por supuesto, contará con una vista que contendrá el formulario de login. Sigamos.
Ahora vamos a crear, dentro de la carpeta de nuestros modelos, un archivo con el nombre User.php. La ruta será CarpetaAplicacion/app/Model/User.php. Escribimos lo siguiente:

<?php
App::uses('AppModel','Model');
/**
 * User Model
 *
 */
class User extends AppModel {

   var$name='User';

/**
 * Display field
 *
 * @var string
 */

   public$displayField='username';

   var$validate=array(
       'username'=>array(
                    'rule'=>array('minLength',1),
                    'required'=>true,
                    'allowEmpty'=>false,
                    'message'=>'Por favor, introduce un nombre'
                    ),
       'password'=>array(
                    'rule'=>array('minLength',1),
                    'required'=>true,
                    'allowEmpty'=>false,
                    'message'=>'Por favor, introduce la contraseña'
                    ),

   );

}

Lo que hemos hecho es crear nuestra clase modelo que conectará con nuestra tabla users de la BD. También usamos la validación de los campos username y password del formulario que posteriormente crearemos en nuestra View.
Continuamos. Volvemos a nuestra carpeta de controladores y creamos un archivo llamado UsersController.php. La ruta será CarpetaAplicacion/app/Controller/UsersController.php. Aquí escribimos ahora el siguiente código:

<?php
App::uses('AppController','Controller');
/**
 * Users Controller
 *
 * @property User $User
 * @property PaginatorComponent $Paginator
 */
class UsersController extends AppController {

/**
 * Components
 *
 * @var array
 */
    public$components=array('Session');
 
    publicfunction autenticar(){
        // Aunque los campos username y password tienen validación para que no estén vacíos,
// volvemos a asegurarnos con el condicional que el campo username del formulario tiene
        //algún valor
        if(empty($this->data['User']['username'])==false)
        {
    	 //Consulta SQL para buscar al usuario con sus credenciales en la BD
$user=$this->User->find('all',array('conditions'=>array(
                'User.username'=>$this->data['User']['username'],
                'User.password'=>$this->data['User']['password'])));
         //Si se ha encontrado al usuario en la consulta
         if($user!=false)
         {
          //Si existe se redirecciona al usuario a la aplicación creando una variable de sesión 
          $this->Session->setFlash(__('Gracias por loguearse!'));
          $this->Session->write('User',$user);
          $this->Redirect(array('controller'=>'ControllerDeTuAplicacion','action'=>'index'));
          exit();
         }
         else
         {
//Si los datos no son correctos se comunica al usuario y se le devuelve al mismo
          //formulario de login
          $this->Session->setFlash(__('Nombre de usuario y/o password incorrectos'));
          $this->Redirect(array('action'=>'autenticar'));
          exit();
         }
        }
    }
}

Veamos qué hace nuestra clase controller. Es imprescindible, como en el archivo AppController, tener cargado el componente Session. Como podemos ver lo tenemos en nuestra variable pública $components. Lo primero que va a hacer la clase es comprobar que se han pasado datos en el campo username desde el formulario. Es cierto que los campos ya están validados desde nuestro Model, pero siempre es interesante comprobarlo también aquí. Si no es correcto, es decir, si el campo está vacío, entonces se redirecciona de nuevo al mismo formulario. De esto se encarga nuestro Model como sabemos, ya que al no haber ninguna variable Session creada reaccionará en consecuencia. Si, por el contrario, hay datos, se ejecuta una consulta en la BD para comprobar que, efectivamente, el usuario y password existen. Si no existen, entonces se le redireccciona al usuario de nuevo a la acción autenticar que hará que nuestro afterFilter del archivo AppController (¿Recuerdas?) compruebe que exista una variable de sesión. Como no es así se le reenvía automáticamente de nuevo al formulario con un mensaje flash indicando que uno o los dos campos no son correctos. Si existe el usuario, entonces se le redirecciona a la página index de la aplicación, no sin antes crear la variable de sesión que nos permitirá superar con éxito el método authenticate de nuestro AppController que es llamado automáticamente desde nuestro vigilante afterFilter.
Ya lo único que nos queda es crear nuestra View que mostrará el formulario para poder loguearse. Vamos a la ruta CarpetaAplicacion/app/View y creamos la carpeta Users. Despues, dentro de ella, creamos el archivo autenticar.ctp con el siguiente código:

<div>
<?php echo $this->Form->create('User'); ?>
	<fieldset>
		<legend><?php echo __('Login aplicación'); ?></legend>
	<?php
		echo $this->Form->input('username');
		echo $this->Form->input('password');
	?>
	</fieldset>
<?php echo $this->Form->end(__('Continuar')); ?>
</div>

Como se puede observar se trata de un simple formulario muy sencillo donde no creo que haya nada que explicar. Pues ya está, con esto hemos terminado. Ahora tenemos un sistema que permite proteger el acceso a nuestra aplicación de todos aquellos usuarios que, previamente, no estén en la base de datos. Obviamente, para poder probarlo, necesitamos entonces tener al menos un usuario en nuestra tabla users. Este ejemplo no contempla la posibilidad de registrarse pero creo que, con este punto de partida, no es nada complicado implementarlo. Pero eso lo dejo para vosotros 🙂 Un saludo.-

Anuncios