Annunci
Al termine di una lunga sperimentazione ecco a voi URL Inspector.  Questo strumento permette di analizzare una URL Internet e dopo avere effettuato le relative interrogazioni ai diversi whois server, nonchè dopo aver parserizzato le relative risposte, compone l'esito in un formato direttamete leggibile in modo da ridurre i tempi di ricerca. Lo strumento è comunque ancora in fase beta, vista la complessità dei controlli che si devono eseguire e l'innumerevole combinazione di URL che si possono comporre. Presto dunque, sperimentate la vostra ricerca, così da poter contribuire all'uscita della prima versione. Pagina di URL Inspector
Autenticazione sicura con Flex - PHP e MySQL PDF Print E-mail
User Rating: / 1
PoorBest 
Written by Luca Guerrieri   
Monday, 05 May 2008 02:00

Oggi ho pensato di presentarvi un progetto che ho sviluppato qualche tempo addietro, per :

1) imparare il PHP (bellissimo !)

2) realizzare un framework per creare siti internet secondo il pattern MVC.

3) imparare come è stato implementato l'object-orientation in php5.

Come dire se vuoi fare qualcosa ... falla in grande!

Il framework implementa sia la tecnologia XML sia Ajax oltre ad avere un possibile back-end MySQL, dico possibile perchè in realtà per realizzare una pagina web, come quelle dei famosi CMS PhpNUKE, Joomla, Midgard ecc.,  basta inserire un file e non appoggiarsi per forza ad un server MySQL, risparmiando sia risorse di sistema sia economiche.

Passiamo ora al solo sistema di autenticazione, visto che è una delle parti progettualmente più complesse ma operativamente più semplici, il resto lo presenterò in un prossimo futuro.

Resta importante specificare che il Login Manager ha la peculiarità di effettuare la fusione e criptazione delle credenziali di accesso, inserite dall'utente, direttamente lato client !!!. Esso, infatti, realizza l'hashing md5 dello username, della password e di una stringa generata casualmente dal sistema e visualizzata direttamente a video in formato immagine (sistema CAPTCHA) inviandole poi al server il quale, ricevendo lo username, conoscendo la stringa casuale (da lui generata) ed avendo ricevuto l'md5 della username-password-stringa casuale, provvede alle successive operazioni.

Per ottimizzare l'autenticazione ho provveduto a realizzare l'invio delle credenziali in una stringa composta da :

username = username inserito   +     login = credenziali criptate

Es.: pippo+123jhfo34xd~5ttTTyhzalmncttsk4585@qq0pP-w        (vi sfido ad indovinare :-) )

in questo modo il sistema effettuerà prima una ricerca dell'utente (pippo) che, se presente, permetterà la continuazione delle operazioni, in caso contrario sarà visualizzato un messaggio di diniego.

Peculiarità di questo sistema  di login:

1) Trasmissione sicura delle credenziali d'accesso (criptate)

2) Invio asincrono, il sistema in effetti implementa una logica di autenticazione a chiave pubblica/chiave privata, ove la chiave pubblica è lo username e password e la chiave privata è di fatto la stringa casuale generata ed inviata al client sotto forma d'immagine. In questo modo un malintenzionato che intercetta il nostro traffico sin dall'inizio, per scoprire username e password, non è in grado di identificarle inquanto:

  • nonostante sia in possesso della stringa casuale non conoscerebbe username e password che viaggiano, al ritorno, in forma criptata.
  • se dovesse conoscere username e password non potrebbe usare la stringa casuale intercettata, perchè è già stata "bruciata" dall'utente durante il login.

3) Sicuro, se l'utente non esiste non si procede ad ulteriori operazioni fra client e server.

4) Unicità delle credenziali d'accesso, l'utente usa le sue ma il sistema riceve un'insieme diverso ogni volta, come in un sistema O.T.P.

5) Elaborazione lato client completamente invisibile ad un malintenzionato che accede fisicamente alla macchina della vittima. La criptazione viene effettuata con un applicativo compilato e residente sul client, quindi non direttamente interpretabile (applicazione Flex su pagina html).

6) Possibilità di applicare algoritmi proprietari di criptazione per aumentarne la segretezza (basta conoscere Javascript o mxml).

7) Delega della segretezza delle credenziali all'utente ed al gestore del sistema informatico (il sistema di autenticazione è sicuro, tutto il resto non è nostro compito ;-) ).

8) Redirezionando l'utente, dopo il login-success, ad una comunicazione con protocollo https, si raggiunge una completa segretezza della trasmissione ed una sicura identificazione dell'utente sin dalla fase di autenticazione.

9) Web oriented, "gira" su tutte le piattaforme PHP-MySQL lato server e con un lettore file swf (noto come file Flash)  lato client.

10)  Uso di tecnologie già note e notevolmente diffuse.

... ah dimenticavo tutto Open Source !!!

Un esempio? li trovate qui

Administrator paperino password
Power User
pippo drowssap
User topolino password
Guest paperone onecent

Ricordando che il sistema è configurato per riconoscere 4 tipi di livelli di autenticazione :

1 Administrator Administrator of site
2 PowerUser Power user of the site
3 User User of the site
4 Guest Guest of the site

L'esito dell'autenticazione visualizzerà una pagina che ne riporta tutte le caratteristiche.

Passiamo ad una piccola analisi del codice :

FlexLogin.mxml

In questo file abbiamo il codice utile per creare l'interfaccia di login, al suo interno troveremo le seguenti funzioni :

Funzione per eseguire il login:

public function makeLogin():String {
return (MD5.encrypt(username.text + password.text + txtCaptcha.text));
}

Funzione per inviare i dati di autenticazione

public function sendInfo():void {
var url:String = "http://localhost/pxaserver/libreria/loginresult.php";
var info:String = "username="+ username.text+"&login="+makeLogin();
var request:URLRequest = new URLRequest(url);
var login:URLVariables = new URLVariables(info);
request.method="POST";
request.data = login;
navigateToURL(request);
}

Funzione per effettuare la registrazione  di un nuovo utente

public function register_user():void{
var url:String = "http://localhost/pxaserver/secure_area/registeruser.php";
var goto:URLRequest = new URLRequest(url);
navigateToURL(goto);
}

Funzione ricorda utente

public function remember_password():void{
var url:String = "http://localhost/pxaserver/secure_area/remember.php";
var goto:URLRequest = new URLRequest(url);
navigateToURL(goto);            
}

Da notare che in ogni funzione la variabile url:String è stata inizializata ad un URL, ricordatevi che quest'ultimo deve essere un URL del vostro server. Es.: http://www.miodominio.it/libreria/loginresult.php

All'interno della funzione makeLogin (che restituisce un risultato di tipo stringa) noterete la chiamata ad un metodo statico "MD5.encrypt". Questa chiamata ci permette di effetture l'hash con MD5, della stringa passata, questa è la stringa che verrà inviata insieme con lo username.

Preciso che non è meta di questo articolo quello di spiegare la compilazione di un file mxml con gli strumenti open-source, presenti in rete, fate comunque riferimento al sito di www.adobe.com, troverete tutti gli spunti del caso.

Passiamo ora al codice lato server.

Abbiamo detto che è stato usato il linguaggio PHP che nella sua versione 5, permette di usare un'orientamento ad oggetti.

Innanzi tutto osserviamo i file denominato index.php che deve essere posizionato all'interno della directory che conterrà in seguito tutti i file che vorremo proteggere dal sistema dio login. Notate come la prima istruzione si aun require ... e la seconda (quindi la prima eseguita) sia una chiamata alla funzione login_session_control(). Questa funzione deve essere inserita in ogni file che vogliamo proteggere.

Index.php

<?php
// inizio controllo sessione area privata
require ('../libreria/libfunz.inc.php');
login_session_control();

// fine controllo sessione per area privata

$sessi = new Session;
print("Il risultato del form di login :<br><br>");
print("Il valore di username : ". $_POST["username"]."<br>");
print("Il valore di password : ". $_POST["password"]."<br>");
print("Il valore di login passato : ". $_POST["login"]."<br>");
echo "<br>ID di sessione = " . $sessi -> get_session_id();
echo "<br>La stringa captcha e' : ".$sessi -> get_session_value("captcha");
echo "<br>La stringa login e' : ".$sessi -> get_session_value("login");
echo "<br><br>".perform_login($_POST["username"],$_POST["password"],$_POST["login"]);
?>

Ecco di seguito un estratto del file Libfunz ed in particolare le due funzioni presentate.

Libfunz.inc.php

Funzione per eseguire il login

function perform_login ($username,$password, $login){
/*
* Funzione per effettuare il login
* $username:    username dell'utente
* $password:    password dell'utente
* $login:        stringa criptata in MD5 del login che contiene
*                 username + password + captcha
*/
$aut = new Autentica;
$aut -> login($username,$password,$login);
return $aut -> login_result();
}

Funzione per controllare la sessione. Questa funzione viene inserita all'interno della prima pagina che deve essere visualizzatadopo il login (quella nell'area privata), in questo modo nel caso non si sia già provveduto ad effettuarte il login, l'accesso verrà negato e si sarà redirezionati all'apposito form delle credenziali.

function login_session_control(){
// da inserire prima di tutto!!!!
/*
* Funzione per controllare se è stato effettuato il login
*/
//if(session_id() == "") { session_start(); }
require ('config.inc.php');
$s = new Session;
$s -> init_session();
if (($s -> get_session_value("login")== null)|| ($s -> get_session_value("login")!="success")){
header("Location:".$login_page);
//print("<script>window.location='".$login_page."'</script>");
}else {
$s -> regenerate_session();
}
}

All'interno della funzione perform_login() si può notare l'istanza della classe Autentica. Quest'ultima serve a gestire in toto il processo di login.

Classe Autentica

<?
/*
Classe per l'autenticazione con chiave privata
Guerrieri Luca This e-mail address is being protected from spambots. You need JavaScript enabled to view it
*/

class Autentica {
//Classe per l'autenticazione
private $username;   
private $password;
private $level;                             //livello utente
private $check_username_result;                //bool risultato username dell'autenticazione
private $check_password_result;                //bool risultato password dell'autenticazione
private $link;                              //il link alla connessione del database
private $login_array;                       //array risualtato dal login
private $md5_string;                        //stringa di login codificata md5
private $s;                                 //puntatore ad una istanza della classe Sessione
private $log;                               //puntatore ad una istanza della classe LOGManager
private $msg_error;                             //puntatore ad una istanza della classe MSGmanager

function Autentica (){
//costruttore
include_once("global.inc.php");
$this -> msg_error= new MSGmanager;              //Istanzia la classe dei messaggi di errore
$this -> s = new Session;                    //Istanzia la classe per estire le sessioni
$this -> s -> init_session();                //inizializza la sessione
$this -> log = new LOGmanager;

}

//Metodo per effettuare il login
public function login($username, $login, $ip) {
//prende in carico il  login ed inizia l'autenticazione
//non abbiamo bisogno di controllare la correttezza della password
//perchè fa parte della stringa di login
include ("config.inc.php");         //Richiede il file di configurazione generale
$this->check_username($username);    //chiama il metodo check_username per controllare se esiste lo $username
$ora= (string)date("d-m-Y H:i:s");
if (($this->check_username_result)== true){
//username buono
$md5_login= $this->username.$this->password.$this -> s -> get_session_value("captcha");
$this->md5_string=md5($md5_login);
if (($this->md5_string)==$login){
//le stringhe di login sono uguali
$this -> level = $this->login_array[0]['level'];
$this -> set_check_username_result(true);
$this -> s -> set_session_var("login", "success");
$this -> s -> set_session_var("time", $ora);
$this -> s -> set_session_var("level", $this->level);
//memorizziamo la sessione nel db
$Qm_s = new QueryManager;
$Qm_s -> set_query('Q_set_session');
$Qm_s -> set_placeholders(array("user_id","session_id","login_time"));
$Qm_s -> set_data(array($this->login_array[0]['username'],$this -> s -> get_session_id(),$ora));
$Qr_s = new QueryResult($Qm_s->get_dynamic_query(),"direct",$this->link);
$logmsg = array ($this->msg_error->print_msg('auth_log_operation_success'),$this->login_array[0]['username'],"session id : ".$this -> s -> get_session_id(),$ip,time());
$this -> log ->write_csv_row_log_file($auth_log, $logmsg);
}else{
//le stringhe di login non sono uguali
$this -> set_check_username_result(false);
$this -> s -> set_session_var("login", "required");
$logmsg=array ($this->msg_error->print_msg('auth_log_operation_fails'),$this->login_array[0]['username'],$this->msg_error->print_msg('auth_log_operation_fails_string'),$ip,time());
$this -> log ->write_csv_row_log_file($auth_log, $logmsg);
}
} else {
//username no buono   
$this-> set_check_username_result(false);
$this -> s -> set_session_var("login", "required");
$logmsg = array ($this->msg_error->print_msg('auth_log_operation_fails'),$username,$this->msg_error->print_msg('auth_log_operation_fails_user'),$ip,time());
$this -> log ->write_csv_row_log_file($auth_log, $logmsg);
}
}

//Metodo che controlla l'esistenza dell'utente
public function check_username($username) {
//si connette al db e controlla se l'utente esiste altrimenti rilascia un messaggio di errore
$this->username=$username;
$Qm = new QueryManager;
$Qm ->set_query('Q_username');
$Qm ->set_placeholders(array('username'));        //imposto i nomi dei placeholders nella query come array
$Qm ->set_data(array($this->username));            //imposto i nomi delle variabili nella query come array
$Qr = new QueryResult($Qm ->get_dynamic_query(),"assoc",$this->link);    //rilascia un array con il risultato della query eseguita
$this-> login_array=$Qr->result;
//print_r($this->login_array); //per controllare il risultato
if ((!is_array($this-> login_array))||(is_null($this-> login_array))){
print ($this->msg_error->print_error('auth_login_query_error'));
}else {
if (count ($this->login_array)>0){
$this->set_check_username_result(true);            //username buono
}else {
$this->set_check_username_result(false);        //username no buono   
}
}
$this -> password=$this->login_array[0]['password'];    //estrae la password
}
//Metodo che controlla se la password inserita è giusta
private function check_password($password){
//Inserire il controllo della password criptata    

if ($this->password == $password){
//la password è giusta
return $this->set_check_password_result(true);
}else {
//la password non è giusta
return $this->set_check_password_result(false);
}
}
//Metodo che rilascia il risultato dell'autenticazione
public function get_check_username_result(){
return $this->check_username_result;
}
//Metodo che imposta il risultato dell'autenticazione
private function set_check_username_result($result){
$this->check_username_result=$result;
}
//Metodo che imposta il risultato dell'autenticazione
private function set_check_password_result($result){
$this->check_password_result=$result;
}
//Metodo che imposta il link al db
public function set_db_link($link){
$this->link=$link;
}
//Metodo che rilascia il risultato dell'autenticazione
public function get_check_password_result(){
return $this->check_password_result;
}
//Metodo che restituisce la password dell'autenticazione
public function get_user_password(){
return $this->password;
}
//Metodo per inserire una sessione nel db tabella sessioni
private function set_session_id(){

}
//Metodo che esegue le operazioni in seguito all'esito del tentativo di login
public function login_result (){
//controlliamo il risultato
return $this->get_check_username_result();
}

}
?>

All'interno della funzione login_session_control() possiamo invece notare la classe Session Quest'ultima gestisce, istanzia e chiude una sessione oltre che rinnovarla per motivi di sicurezza.

Classe Session

<?php
class Session {

function Session() {
//costruttore della classe (overload)
require('config.inc.php');                  //Richiede il file di configurazione generale
$this -> error= new MSGmanager;             //istanzia la classe per i messaggi
//if ($init==true){$this -> init_session();}  //inizializza la sessione
}

//Metodo per cancellare un Session ID
public function del_session() {
$_SESSION=array();
if (IsSet ($_COOKIE[session_name()])){
setcookie(session_name(), '', time()-42000, '/');
}
session_destroy();
}

//Metodo per cancellare un cookie
public function unset_cookie($cookie_name,$cookie_value){
if(IsSet($_COOKIE[$cookie_name])){
setcookie($cookie_name,$cookie_value,time()-31536000);
}
}

//Metodo per impostare una sessione
public function init_session() {
session_start();             //inizia o continua la sessione
//$_SESSION[$session_var] = $session_value;
//$this -> set_cookie($session_var,$session_value);
}

//Metodo per inizializzare una variabile di Sessione
public function set_session_var($session_var,$session_value) {
$_SESSION[$session_var] = $session_value;
}

//Metodo per resettare una variabile registrata in sessione
public function unset_session_var($session_var) {
unset ($_SESSION[$session_var]);
}

//Metodo per rigenerare una sessione
public function regenerate_session(){
return session_regenerate_id();
}


//Metodo per impostare i cookie
public function set_cookie($cookie_name,$cookie_value){
$this -> cookie_enable();
setcookie($cookie_name,$cookie_value,time()+31536000);
}

//Metodo per sapere se i cookie sono abilitati
public function cookie_enable ($disabled_cookie_url=""){
if(!IsSet($_COOKIE['PHPSESSID'])){
//AGGIUNGERE MESSAGGIO DEL MSG MANAGER
print ("Per poter usufruire di questi servizi si devono avere i cookie abilitati");
return $cookie_enable=false;
}else{
return $cookie_enable=true;
}
}
//Metodo per leggere i cookie
public function get_cookie_value($var) {
if (IsSet($_COOKIE[$var])){
return $_COOKIE[$var];
}else {
//print ("Attenzione non c'e' la variabie cercata nel cookie");
//se la variabile nel cookie non è presente ritorna false
return false;
}

}
//Metodo per leggere una sessione
public function get_session_value($var) {
if (IsSet($_SESSION[$var])){
return $_SESSION[$var];
}else {
//print ("Attenzione non c'e' la variabie cercata nella sessione");
//se la variabile non è presente ritorna false
return false;
}

}
//Metodo per leggere il SessionID da un cookie di sessione
public function get_cookie_session_id() {
if (IsSet($_COOKIE['PHPSESSID'])){
return $_COOKIE['PHPSESSID'];
}else {
print ("Attenzione non è stata impostata una sessione valida");
}

}
//Metodo per leggere il SessionID
public function get_session_id() {
return session_id();
}
}
?>

Infine, quando effettuiamo l'invio dei dati, viene invocato, per mezzo di query string, il file loginresult.php. Se tutto il processo di login è andato a buon fine permetterà la visualizzazione delle variabili inerenti l'autenticazione.

Loginresult.php

<?php
include_once ('global.inc.php');
require_once ("config.inc.php");
require_once ("libfunz.inc.php");

if (perform_login($_POST["username"],$_POST["login"])==true){
//se il login ha successo redirezioniamo all'area privata
$s = new Session;
$s -> init_session();
if ($s->get_session_value("level")==1){header ("Location:".$admin_area);}else{header ("Location:".$secure_area);}
}else {
//se il login non ha successo redirizioniamo al login page
header ("Location:".$login_page);
//codice per pop-up di ritorno come
//utente disabilitato
//utente non trovato
//password o hash errati
}
?>


Avrete notato come le classi presentate fanno uso di altre classi che per ora non presento perchè degne di un'analisi dettagliata, a parte.

 

Last Updated on Sunday, 11 October 2009 13:58
 
Creative Commons LicenseTutti i contenuti riportati in questo sito vengono rilasciati con la seguente licenza : Creative Commons Attribution - NonCommercial - ShareAlike Si precisa, inoltre, che tutti i singoli marchi registrati sono dei rispettivi proprietari. Diritti d’autore e proprietà industriale: I testi e le immagini pubblicati in questo sito sono di proprietà esclusiva dei relativi autori i quali indicano per ogni opera la relativa licenza di rilascio. In caso, quest'ultima, non sia espressamente indicata si assumerà, a favore del relativo autore di ogni opera, la Creative Commons Attribution - NonCommercial - ShareAlike. Ogni singolo autore è responsabile dei contenuti da egli realizzati. Note ex L. 62/01 - I contenuti di questo sito non hanno carattere di periodicità e non rappresentano "prodotto editoriale". I controlli sui contenuti riguardano solo ed esclusivamente quelli pubblicati direttamente da questo  sito. I link ad altre pagine non rientrano nei controlli in questione.