Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Apache: personalizzare il sistema di autenticazione

Come collegare Apache ad un sistema di autenticazione personalizzato attraverso i moduli mod_authnz_external e mod_auth_external e PHP.
Come collegare Apache ad un sistema di autenticazione personalizzato attraverso i moduli mod_authnz_external e mod_auth_external e PHP.
Link copiato negli appunti

Proseguiamo la trattazione dei meccanismi di autenticazione forniti da Apache con un argomento un po' particolare: come utilizzare un programma esterno al web server per verificare le credenziali immesse dall'utente. In questo articolo vedremo, in altre parole, come "passare" il controllo della password di autenticazione ad un programma esterno ad Apache come, ad esempio, uno script PHP.

Nei precedenti articoli, Apache: autenticazione di base con .htaccess e Apache: autenticazione digest e utilizzo di file Dbm, abbiamo descritto, o almeno menzionato, molti moduli che consentono di accedere ai più comuni sistemi di memorizzazione delle password: file di testo, file binari DBM o DB, tabelle di database, directory Ldap.

Potremmo però trovarci nella sfortunata situazione in cui non esista il modulo appropriato per comunicare con il sistema da noi adottato. Scriverne uno ex-novo risulta piuttosto complesso e richiede conoscenze non banali dei meccanismi di funzionamento di Apache. Per fortuna possiamo contare su un modulo particolarmente flessibile mod_authnz_external, grazie al quale ci limiteremo a redigere il programma che effettuerà l'autenticazione. Il relativo progetto è ospitato sulle pagine di Google Code, quindi non ci resta che fare rotta verso quella direzione.

Nelle prossime pagine introdurremo il modulo e creeremo un esempio pratico di utilizzo facile da comprendere.

Mod_authnz_external o mod_auth_external?

Avevamo già accennato al sistema di autenticazione ed autorizzazione introdotto con Apache 2.1. Alla base dello schema vi sono i due moduli di autenticazione mod_auth_basic e mod_auth_digest. Essi comunicano con i provider di autenticazione che forniscono il servizio di autenticazione vero e proprio. I nomi dei moduli di questa seconda categoria hanno il prefisso mod_authn_, come mod_authn_file o mod_authn_dbm. Infine per ultimi entrano in azione i moduli di autorizzazione il cui prefisso è mod_authz_, come mod_authz_user o mod_authz_groupfile. Un ultimo gruppo di moduli, che integra le funzioni di provider di autenticazione e di autorizzazione, ha come prefisso mod_authnz_.

È chiaro dunque come mod_authnz_external, pur avendo sostanzialmente le stesse funzionalità di mod_auth_external, si integri nel più recente schema. Attenzione dunque alla versione del programma che andremo a prelevare, essa dovrà corrispondere alla versione di Apache installata. Di seguito presupporremo di lavorare con Apache 2.2 e quindi di utilizzare mod_authnz_external 3.2.

Il modulo è strutturato in modo che eventuali malfunzionamenti nel programma esterno non possono mandare in crash il web server. Il programma esterno, d'altro canto, può girare con un utente diverso da Apache (setuid). In questo modo possiamo concedere solo a quest'ultimo l'accesso al sistema di memorizzazione delle password e concentrare su di esso gli sforzi volti a migliorare la sicurezza. La presenza di bug in Apache, o in CGI da esso eseguiti, non consentiranno comunque l'accesso alle credenziali.

È chiaro che l'esecuzione di un ulteriore programma richiederà risorse aggiuntive, il che rappresenta una caratteristica negativa rispetto agli altri moduli.

Un'ultima considerazione prima di passare all'azione: mod_authnz_external funziona con l'autenticazione di base HTTP, ma non con l'autenticazione digest. Il che ha una sua logica: in caso contrario il sistema di memorizzazione delle password dovrebbe prevedere il medesimo algoritmo di cifratura.

Nella prossima pagina vedremo come installare il modulo mod_authnz_external.

Installiamo il modulo

L'ambiente di lavoro cui ci riferiremo negli esempi sarà Fedora 11 con Apache 2.2. Non esistendo un pacchetto rpm relativo a mod_authnz_external dovremo procedere alla sua compilazione con il tool Apxs. Al termine del processo otterremo un modulo caricato dinamicamente da Apache. Innanzitutto assicuriamoci che sulla nostra linux box siano presenti GCC e httpd-devel altrimenti installiamoli ricorrendo a Yum.

Puntiamo il browser verso la pagina di Google Code dedicata a mod-auth-external e preleviamo il file compresso mod_authnz_external-3.2.5.tar.gz. Assumiamo i privilegi di root e scompattiamo l'archivio in una directory di lavoro a scelta, ad esempio /usr/src. Posizioniamoci al suo interno e compiliamo il modulo con il comando:

$ apxs -c mod_authnz_external.c 

Ora installiamolo digitando:

$ apxs -i -a mod_authnz_external.la

Nella directory /etc/httpd/modules, collegamento simbolico a /usr/lib64/httpd/modules/, troveremo ora anche mod_authnz_external.so. Mentre all'interno del file di configurazione principale, /etc/httpd/conf/httpd.conf, noteremo l'aggiunta di una riga simile alla seguente:

LoadModule authnz_external_module /usr/lib64/httpd/modules/mod_authnz_external.so

Si tratta della direttiva che carica dinamicamente il modulo all'avvio del web server. Se la versione del sistema operativo non fosse a 64 bit nei percorsi specificati troveremmo lib al posto di lib64, oppure LoadModule potrebbe semplicemente fare riferimento al percorso relativo modules/mod_authnz_external.so.

Installato il modulo dobbiamo configurare Apache affinché possa utilizzarlo secondo i nostri scopi. Ricorriamo dunque alla direttiva DefineExternalAuth che ha la seguente sintassi:

DefineExternalAuth keyword method location

Per compatibilità con le precedenti versioni possiamo anche usare:

AddExternalAuth keyword location
SetExternalAuthMethod keyword method

Vediamo nel dettaglio il significato dei parametri della direttiva o delle due direttive alternative:

  • keyword: è un nome di fantasia scelto per identificare il sistema di autenticazione esterna, possiamo definirne più di uno attribuendo a ciascuno una diversa parola chiave.
  • method: identifica il sistema con cui nome utente e password vengono passati al programma di autenticazione, i valori possibili sono pipe, enviroment, checkpassword e function.
  • location: specifica come individuare il sistema di autenticazione, nella maggior parte dei casi sarà il percorso del programma esterno utilizzato.

Negli esempi che seguono prenderemo in considerazione il metodo pipe, che è anche il metodo di default. In questo caso le credenziali vengono lette dallo standard input: dalla prima riga il nome utente, dalla seconda la password. Per ulteriori approfondimenti vi rimando alle pagine del progetto o ai file di documentazione inclusi nella tarball scaricata.

La seconda parte dell'articolo verrà pubblicata la settimana prossima.

Esempio pratico di utilizzo

Per mantenere il consueto taglio pratico disegniamo un possibile scenario in cui faremo ricorso a mod_authnz_external, è evidente infatti che le possibilità sono infinite date le caratteristiche del modulo.

Supponiamo di dover gestire un web server Linux Fedora 11 con Apache 2.2 e PHP 5.2 su cui si trova il sito www.miosito.it. Vogliamo proteggere una directory che chiameremo "privata" in modo tale che solo alcuni utenti, in possesso di apposite credenziali, possano accedervi. Sin qui nulla di speciale, ma per complicarci la vita, immaginiamo che nomi utente e password siano memorizzati in un database Microsoft SQL Server che gira su una macchina Windows con numero IP 11.22.33.44. In particolare ci riferiremo alla versione liberamente scaricabile Microsoft SQL Server 2005 Express Edition.

La soluzione adottata consisterà nella creazione di uno script PHP che acceda al database e verifichi le credenziali. Configureremo poi Apache perché possa comunicare con tale script tramite mod_authnz_external e possa quindi regolare l'accesso alla directory protetta.

Una doverosa premessa: il codice riportato ha valenza puramente esemplificativa ed è quindi ridotto all'osso per essere maggiormente comprensibile. In un'applicazione reale andrebbero curati tutti gli aspetti di gestione degli errori e di sicurezza.

Cominciamo dalla configurazione del database e dalla creazione dello script PHP, che analizzeremo nella prossima pagina.

Connessione al database e creazione script

Il primo scoglio da superare è l'accesso al database Microsoft, possiamo brillantemente risolvere il problema con l'estensione PHP Mssql. Se non è già presente sul nostro sistema provvediamo ad installarla:

$ yum install php-mssql

Supponiamo ora che SQL Server accetti connessioni dall'esterno e sia in ascolto sulla porta 1120, di aver inoltre creato un database utenti ed un account che possa accedere a tale database. All'interno del database sarà presente una tabella users con tre campi: id, login e passwd che non hanno bisogno di ulteriori spiegazioni. Le password saranno memorizzate in chiaro.

Ecco lo script PHP che chiameremo php_auth.php:

<?php
//dati per la connessione
$myServer = "11.22.33.44:1120";
$myUser = "mioaccount";
$myPass = "miapassword";
$myDB = "utenti";

//connessione al database
$link = mssql_connect($myServer, $myUser, $myPass);

//selezione del database
$selected = mssql_select_db($myDB, $link);

//leggo l'input
$name = trim(fgets(STDIN));
$pwd = trim(fgets(STDIN));

//interrogo il database
$query = "SELECT id FROM users 
          WHERE login='$name' AND passwd='$pwd'";

$result = mssql_query($query);

$numRows = mssql_num_rows($result);

//chiudo la connessione
mssql_close($link);

//se le credenziali sono corrette restituisco 
//il valore 0 altrimenti 1
if($numRows == 1)
 exit(0);
else
 exit(1);

Come detto, lo script è molto semplice e, secondo quanto prescritto, fornirà il valore 0 in caso positivo ed 1 in caso negativo. È possibile completare il programma con altri codici numerici di errore personalizzati, utili per il debug. Ad esempio si può impostare un valore che identifichi l'impossibilità di connessione al server o controlli simili.

Nella pagina seguente vedremo come configurare Apache.

Configurazione di Apache

Passiamo ora alla configurazione di Apache e, supponendo di aver definito un host virtuale per il nostro sito, inseriamo la direttiva DefineExternalAuth all'interno del contenitore <VirtualHost>:

<VirtualHost 55.66.77.88>
 ........
 DefineExternalAuth phpauth pipe '/usr/bin/php /percorso/php_auth.php'
 ........
</VirtualHost>

È immediato desumere che la parola chiave scelta per la nostra autenticazione è phpauth, che utilizzeremo il metodo di comunicazione pipe ed infine che dovrà essere eseguito, mediante PHP CLI, lo script php_auth.php posizionato in /percorso/.

Dopo aver definito l'autenticazione esterna dobbiamo impiegarla per proteggere la nostra directory. Le seguenti direttive potranno essere inserite in un contenitore <Directory> all'interno del <VirtualHost>, oppure nel classico file .htaccess posizionato nella directory privata.

AuthType Basic
AuthName "Area Protetta"
AuthBasicProvider external
AuthExternal phpauth
Require valid-user

Ricordo che per l'utilizzo di .htaccess deve essere attivata l'opzione di AllowOverride, AuthConfig.

Descriviamo brevemente le istruzioni dell'esempio, cui dovreste essere ormai avvezzi se avete seguito i precedenti due articoli. Con Authtype impostiamo l'utilizzo dell'autenticazione di base, con AuthName un'etichetta per definire l'area protetta (o come visto in precedenza il realm). AuthBasicProvider stabilisce che il metodo di autenticazione si baserà su un programma esterno, mentre AuthExternal lo individua mediante la parola chiave phpauth che avevamo definito con DefineExternalAuth. Infine con Require valid-user richiediamo che l'utente sia presente nella tabella di SQL Server e che abbia comunicato le corrette credenziali.

A questo punto un riavvio di Apache renderà effettive le nuove impostazioni e, cercando di accedere a http://www.miosito.it/privata, ci vedremo proporre la classica finestra di login del browser. Nome utente e password inseriti verranno verificati con una query sul database utenti e, se corretti, potremo accedere ai contenuti privati.

Siamo giunti al termine della trattazione con la quale spero soprattutto di aver fatto intravvedere le innumerevoli possibilità offerte da mod_authnz_external. Potremmo creare un sistema di autenticazione che si basi sugli utenti di un sistema unix, o quelli di un server di posta o ancora di un server Samba e chi più ne ha più ne metta. Alcuni "autenticatori" sono già stati realizzati e sono liberamente distribuiti, prima di sprecare tempo ed energie conviene quindi verificarne l'esistenza. Un buon punto di partenza sono sicuramente le pagine del progetto a questo dedicate.

Ti consigliamo anche