Auth Component: gestione dei permessi semplice e immediata

Una volta autenticato un utente si può facilmente controllare il suo operato intercettando ogni azione eseguita all’interno dell’applicazione senza ricorrere alle ACL.

Si possono definire controller/action per le quali non richiedere l’autenticazione definendo il valore dell’attributo
$allowedActions = array('pages'=>'display')
oppure impostandolo dinamicamente attraverso il metodo
$this->Auth->allow(array('pages'=>'display', 'users'=>'index'));

Per determinare il tipo di controllo sulle autorizzazioni da eseguire bisogna impostare l’attributo $this->Auth->authorize che può assumere i seguenti valori:

  • controller l’autorizzazione per accedere all’action richiesta è concessa dal metodo Controller::isAuthorized() che deve essere implementato
  • actions esegue un controllo dell’action richiesta richiamando il metodo AclComponent::check(), quindi richiede l’impiego delle ACL.
  • crud esegue la validazione delle mapActions usando il metodo AclComponent::check()
  • array(‘model’=> ‘name’) esegue la validazione della mapActions usando il metodo model $name::isAuthorize(user, controller, mapAction)
  • object esegue la validazione di Controller::action usando object::isAuthorized(user, controller, action)

Controller

Quando si imposta $this->Auth->authorize to ‘controller’, Auth component cercherà un’action chimata ‘isAuthorized’ per sapere se un utente è autorizzato o meno. Come nell’esempio che segue.

function isAuthorized() {
		if (isset($this->params[Configure::read('Routing.admin')])) {
			if ($this->Auth->user('admin') == 0) {
				return false;
			}
		}
		return true;
   }

Auth Component: pieno controllo dell’autenticazione

Come visto negli appunti precedenti, con la semplice attivazione il componente ha dei comportamenti predefiniti durante la fase di autenticazione che potrebbe essere necessario cambiare.
Inoltre vengono messi a disposizione metodi e proprietà utili, oltre che per la gestione dei permessi, in varie occasioni.

Personalizzare l’autenticazione
Impostando alcuni attributi, si determinano i comportamenti del componente.
Di seguito riporto la descrizione di alcune impostazioni di interesse legate all’autenticazione.

$autoRedirect = true
Determina se dopo l’avvenuta autenticazione AuthComponent redireziona automaticamente alla pagina cercata o no.

$fields = array('username' => 'username', 'password' => 'password')
Permette di specificare il nome dei campi usati nell’$userModel diversi da quelli di default necessari all’identificazione.
Ad esempio: array(‘username’ => ‘login_name’, ‘password’ => ‘passwd’).

$loginError = null
Si può impostare il messaggio di errore che viene utilizzato per comunicare la mancata corrispondenza di userid e password.
Questo è l’unico messaggio che viene visualizzato per una questione di sicurezza, così non vengono fornite indicazioni circa l’errore di autenticazione occorso.
Il messaggio qui impostato non viene visualizzato automaticamente nella session Flash, ma deve essere impostato nella view nel seguente modo
if ($session->check(‘Message.auth’)) $session->flash(‘auth’);

$authError = null
Messaggio di errore che appare quando si tenta di accedere a un’area per la quale è richiesta l’autenticazione.

$loginRedirect = null
Quando si richiede l’accesso a una pagina e si viene ridirezionati alla pagina di login $loginAction, dopo l’autenticazione l’utente viene rimandato alla pagina inizialmente richiesta, senza doverla richiedere nuovamente dopo il login.
Se $loginAction non è impostata, l’utente viene ridirezionato alla pagina specificata in $loginRedirect

$logoutRedirect = null
L’azione di defautl alla quale viene ridiretto l’utente dopo il logout. L’URL del redirect viene fornita da AuthComponent::logout() che di default restituisce $loginAction.

$loginAction = null
E’ una stringa o un array che definisce l’URL per la richiesta di login.
Se non impostata, AuthComponent la imposta come (pluralize) $userModel / login , a meno che non venga impostata $loginRedirect

$userModel = 'User'
Il nome del Model utilizzato per eseguire l’autenticazione degli utenti, ovvero l’oggetto che detiene username e password degli utenti. Come visto, il valore di default è il model User.

$userScope = array()
Si possono aggiungere delle condizioni aggiuntive per la verifica dell’utente.
Ad esempio se si vuole permettere l’accesso ai soli utenti che abbiano il campo “attivato” abilitato allora si può definire array(‘User.attivato’ => 1). In questo modo, anche se l’utente inserisce la giusta userid e password gli verrà permesso l’accesso solo se il suo stato è “attivato”.

$sessionKey = null
Definisce il nome della chiave di sessione che contiene i dati sull’utente autenticato.
Se non è specificato il valore di default è “Auth.{$userModel}”.

Queste impostazioni devono essere definite nel controller

function beforeFilter(){
		$this->Auth->authError = "Per accedere alla pagina richiesta bisogna autenticarsi";
		$this->Auth->loginError = 'Tentativo di accesso fallito. Controllare username e password.';
	}

Auth Component: creare un utente, eseguire il login e il logout

Una volta attivato il component, creata la tabella degli utenti e la maschera per il login, è il momento di creare un utente per verificare il corretto funzionamento dell’autenticazione. Ecco due modi di farlo.

Inserimento manuale nella tabella users

Posso inserire i dati nella tabella attraverso il client MySQL o un altro tool grafico (io uso phpMyAdmin ) tenendo presente che la password deve essere converita con la funzione hash utilizzata da Cake, la seguente:

hashpwd = sha1 ( salt + plain_password )

dove salt è la stringa di sicurezza configurata durante l’installazione di CakePHP presente nel file \app\config\core.php.
sha1 è l’algoritmo utilizzato per default da Cake per la funzione hash, ma è possibile cambiare metodo con MD5 e SHA256

Gestione utenti

Creo una gestione completa degli utenti sulla tabella users usando il bake da riga di comando così da poter inserire il primo utente.
A questo punto, seguendo il naming canonico, accedo alla mia gestione degli utenti http://mywebspace/users/ e…. vengo rimandato alla pagina di login !!
Per accedere, almeno temporaneamente alle azioni di users, si interviene su app_controller.php, dove avevamo attivato $authComponent e si inserisce


function beforeFilter()	{
     $this->Auth->allow();
}

A questo punto cake concede l’accesso a qualsiasi azione e possiamo andare a creare l’utente che ci interessa.
Finito l’inserimento, rimuoviamo la riga con il metodo allow() e proviamo a d accedere di nuovo a http://mywebspace/users/.
Ci dovrebbe chiedere nuovamente la userdi – password, ma questa volta si può inserire l’utente inserito e accedere alla sezione della gestione utenti.

Da notare due cose: quando inserisce ad esempio l’URL http://mywebspace/articles/view/234 l’utente viene rimandato a http://mywebspace/users/login e dopo aver effettuato il login, viene reindirizzato sull’URL da lui richiesta in precedenza.
L’altra cosa da notare è che sulla password immessa in fase di inserimento utente, viene automaticamente eseguito l’hash prima del salvataggio in tabella, senza bisogno di aggiungere alcun codice nel controller, nel model o altrove.

Il log out
Per chiudere la sessione è sufficente creare un’action nel controller nel quale invocare il metodo logout di Auth

function logout(){
		$this->Session->setFlash("L\'utente è uscito regolarmente!");
		$this->redirect($this->Auth->logout());
	}

Auth Component: attivazione e quickstart

Attivazione del component Auth

Ho appena installato CakePHP e configurato il database completamente vuoto.
Mi appare la pagina iniziale di Cake, con le indicazioni canoniche.

Creo il file /app/app_controller.php e dichiaro come componente Auth

class AppController extends Controller {
	var $components = array('Auth');
}

Il component è subito attivato e ricaricando la pagina si ottiene un errore perchè si è stati reindirizzati all’URL /users/login.
In pratica essendo attivato in ogni pagina richiesta, il sistema riconosce che l’utente non è autenticato e considera necessaria l’autenticazione per accedere a qualsiasi pagina del sito.
Quindi avviene il reindirizzamento verso l’indirizzo di default /users/login per far si che l’utente si possa autenticare.

Chiaramente si riceve un messaggio di errore se la pagina ancora non esiste, ovvero il controller e la view relativa.

La struttura necessaria

Servono quindi:

  • un model che permetta di conservare e confrontare i dati dell’utente per l’accesso (userid e password)
  • un controller per le azioni relative all’utente (login, logout)
  • una view per il form di autenticazione

La tabella

CREATE TABLE IF NOT EXISTS `users` (
  `id` int(5) unsigned NOT NULL,
  `username` varchar(30) NOT NULL,
  `password` varchar(30) NOT NULL,
  `nome` varchar(60) NOT NULL,
  `cognome` varchar(100) NOT NULL,
  `active` tinyint(1) unsigned NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

Gli unici campi essenziali sono username e password. Si possono utilizzare anche nomi diversi per questi campi, purchè si impostino correttamente nel component (vedi sotto).

Il model

class User extends AppModel {
	var $name = 'User';
}

Il controller

class UsersController extends AppController {

	var $name = 'Users';
	var $helpers = array('Html', 'Form' );

	function login(){
	}
}

Il view (login.ctp)


Login

create('User', array('action' => 'login'));?> input('username');?> input('password');?> submit('Login');?> end(); ?>

A questo punto, accedendo a qualsiasi pagina dell’applicazione, Cake intercetta la richiesta e prima di soddisfarla, controlla che l’utente sia autenticato.
In caso negativo esegue un redirect sulla pagina di login.