Implementazione Ajax con Php per non fare scadere le sessioni...

516 views
Skip to first unread message

Alessandro Marinuzzi

unread,
Oct 11, 2012, 2:25:32 AM10/11/12
to Php
Ciao a tutti, vengo subito al nocciolo della questione, sono su Aruba e non posso usare per problemi vari session_set_save_handler perchᅵ su Aruba ho il NFS sul quale Flock non funziona ( shared server ) e poi dovrei salvare le sessioni sul mio sito web invece che nella cartella tmp del server. Non voglio neanche cambiare cartella per le sessioni perchᅵ non mi fido a mettere le sessioni su una cartella del mio sito che dovrei proteggere con .htaccess. E poi in questo ultimo caso dovrei crearmi una funzione di garbage collector da richiamare ogni tot per cancellare le sessioni inutilizzate e ormai scadute visto che il Garbage Collector da quello che ho potuto appurare almeno su Aruba non ripulisce in automatico nei percorsi personalizzati con session_save_path(). Tutto questo prologo per spiegare che su Aruba le sessioni dopo 20 minuti di inattivitᅵ scadono e se l'utente si allontana per fare la spesa o per rispondere al telefono o per girarsi i pollici e si ritrova la sessione scaduta. A questo punto mi sono reinventato la ruota. Ho scritto un pᅵ di Ajax con il quale ho chiamato ogni 19 minuti (un minuto prima che scadano le sessioni = 20 minuti) un file php che ho chiamato keep-alive.php. Lo scenario: l'utente fa scadere la sessione per inattivitᅵ e in automatico dopo 19 minuti parte una richiesta Ajax che interroga il file keep-alive.php che verifica se le sessioni sono scadute e rigenera le sessioni inviandole alla pagina php corrente che ne ha fatto la richiesta. In questo modo ho aggirato la scadenza delle sessioni per inattivitᅵ dopo 20 minuti e l'utente puᅵ allontanarsi e ritrovarsi la sessione rigenerata e concludere le operazioni che doveva fare.

Vi posto il codice Ajax che voglio usare:

function GetXmlHttpObject(handler) {
  var objXmlHttp = null;
  if (navigator.userAgent.indexOf("MSIE") >= 0) {
    var strName = "Msxml2.XMLHTTP";
    if (navigator.appVersion.indexOf("MSIE 5.5") >= 0) {
      strName = "Microsoft.XMLHTTP";
    }
    try {
      objXmlHttp = new ActiveXObject(strName);
      objXmlHttp.onreadystatechange = handler;
      return objXmlHttp;
    }
    catch(e) {
      alert("Spiacente, il tuo Browser non supporta chimate Ajax");
      return;
    }
  }
  if (navigator.userAgent.indexOf("Mozilla") >= 0) {
    objXmlHttp = new XMLHttpRequest();
    objXmlHttp.onload = handler;
    objXmlHttp.onerror = handler;
    return objXmlHttp;
  }
}
function keepalive() {
  var url = "keep-alive.php";
  xmlHttp = GetXmlHttpObject(returnkeepalive);
  xmlHttp.open("GET", url, true);
  xmlHttp.send(null);
}
function returnkeepalive() {
  if (xmlHttp.readyState == 4 || xmlHttp.readyState == "complete") {
    var returntext = xmlHttp.responseText;
    alert(returntext);
  }
}
function init() {
  window.setInterval("keepalive()", 1140000); /* 19 minuti esatti */
}
window.onload = init;

Ecco un esempio di file keep-alive.php:

<?php
  session_start();
  session_regenerate_id(TRUE);
  header('Content-type: text/html;charset=iso-8859-1');
  $chars_cmid = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345689';
  $length_cmid = 20;
  $comment_id = '';
  for ($i_cmid = 0; $i_cmid < $length_cmid; $i_cmid++) {
    $pos_cmid = mt_rand(0, strlen($chars_cmid) -1);
    $comment_id .= substr($chars_cmid, $pos_cmid, 1);
  }
  $cmid = $comment_id;
  if ((!isset($_SESSION['cmid'])) || (empty($_SESSION['cmid']))) {
    $_SESSION['cmid'] = $cmid;
    $cmid = $_SESSION['cmid'];
  } else {
    $cmid = $_SESSION['cmid'];
  }
  $chars_psid = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345689';
  $length_psid = 20;
  $post_id = '';
  for ($i_psid = 0; $i_psid < $length_psid; $i_psid++) {
    $pos_psid = mt_rand(0, strlen($chars_psid) -1);
    $post_id .= substr($chars_psid, $pos_psid, 1);
  }
  $psid = $post_id;
  if ((!isset($_SESSION['psid'])) || (empty($_SESSION['psid']))) {
    $_SESSION['psid'] = $psid;
    $psid = $_SESSION['psid'];
  } else {
    $psid = $_SESSION['psid'];
  }
  echo "Risulti inattivo da oltre 20 minuti e la Sessione ᅵ scaduta.\nAdesso ᅵ stata rigenerata per altri 20 minuti in automatico.\nNon farla scadere nuovamente, grazie e buon proseguimento.";
?>
Come potete notare nell'esempio keep-alive.php rigenero solo delle sesioni che mi servono come "ticket" per convalidare il post... ossia se l'utente posta, la sessione viene distrutta cosᅵ se torna indietro per ripostare un duplicato si ritrova la sessione scaduta e compare a video un messaggio che lo avverte che la sessione ᅵ scaduta o che il post ᅵ duplicato e lo rimando nella home del mio sito (index.php).

Secondo voi questa mia pratica ᅵ fattibile? Ho testato la cosa e funziona a meraviglia ma ᅵ abbastanza sicura? A me sembra piᅵ sicura che mettere le sessioni in una cartella del mio sito web, dove se capita qualcosa al server (ogni scenario possibile) mi ritrovo la cartella accessibile a tutti con i file di sessione leggibili e la cosa mi spaventa un pᅵ... preferisco che i dati di sessione li gestisca il server e non io per motivi di sicurezza. Cosa ne pensate? Ogni critica ᅵ benvenuta :-)
-- 
Alessandro Marinuzzi
--------------------
http://www.alecos.it
--------------------

Marcello Vezzelli

unread,
Oct 11, 2012, 3:03:35 AM10/11/12
to zb-p...@googlegroups.com
Il 11/10/2012 08:25, Alessandro Marinuzzi ha scritto:
rispondere al telefono o per girarsi i pollici e si ritrova la sessione scaduta. A questo punto mi sono reinventato la ruota. Ho scritto un pò di Ajax con il quale ho chiamato ogni 19 minuti (un minuto prima che scadano le sessioni = 20 minuti) un file php che ho chiamato keep-alive.php. Lo scenario: l'utente fa scadere la sessione per inattività e in automatico dopo 19

Dal phpinfo di aruba:

session.gc_maxlifetime    1440    1440

1440/60=24 minuti.
In realtà la sessione viene fisicamente eliminata in un momento successivo, che dipende dal numero di accessi al sito e dai valori session.gc_probability e session.gc_divisor.

Una riga di php:
ini_set('session.gc_maxlifetime',8*60*60);

Sessione di 8 ore lavorative, sperando che l'utente non si giri i pollici per 8 ore...
testato su aruba, funzionante da alcuni anni.

ciao
Marcello

Alessandro Marinuzzi

unread,
Oct 11, 2012, 3:56:28 AM10/11/12
to zb-p...@googlegroups.com
Il 11/10/2012 09:03, Marcello Vezzelli ha scritto:
Il 11/10/2012 08:25, Alessandro Marinuzzi ha scritto:
rispondere al telefono o per girarsi i pollici e si ritrova la sessione scaduta. A questo punto mi sono reinventato la ruota. Ho scritto un pò di Ajax con il quale ho chiamato ogni 19 minuti (un minuto prima che scadano le sessioni = 20 minuti) un file php che ho chiamato keep-alive.php. Lo scenario: l'utente fa scadere la sessione per inattività e in automatico dopo 19

Dal phpinfo di aruba:

session.gc_maxlifetime    1440    1440

idem per me... stessi valori... solo che da me ini_set('session.gc_maxlifetime',86400);non funziona, dopo 20 minuti esatti la sessione scade per inattività dell'utente mentre se l'utente fa qualcosa non scade mai o al limite a fine operazioni quando viene invocato sessio_destroy();
1440/60=24 minuti.
lo so ma da me sono 1200 effettivi mentre nominali sono 1440????

In realtà la sessione viene fisicamente eliminata in un momento successivo, che dipende dal numero di accessi al sito e dai valori session.gc_probability e session.gc_divisor.

Una riga di php:
ini_set('session.gc_maxlifetime',8*60*60);

Sessione di 8 ore lavorative, sperando che l'utente non si giri i pollici per 8 ore...
testato su aruba, funzionante da alcuni anni.

Scusa la domanda ma tu hai hosting con server condiviso come me? (hosting linux su CentOS)....

piccola nota, ho appurato che la sessione è nominalmente di 24 minuti però scade dopo 20 minuti dai test che ho eseguito minuziosamente sul mio host... fammi sapere ciao e grazie.
ciao
Marcello

--
Hai ricevuto questo messaggio perché sei iscritto al gruppo "zb-php-it" di Google Gruppi.
Per postare messaggi in questo gruppo, invia un'email a zb-p...@googlegroups.com.
Per annullare l'iscrizione a questo gruppo, invia un'email a zb-php-it+...@googlegroups.com.
Per ulteriori opzioni, visita il gruppo all'indirizzo http://groups.google.com/group/zb-php-it?hl=it.

giovanni battista lenoci

unread,
Oct 11, 2012, 4:25:19 AM10/11/12
to zb-p...@googlegroups.com
La butto li perchè è da anni che non uso aruba, ma hai controllato anche il tempo di vita del cookie che conserva il session_id?

Ciao

--
Giovanni Battista Lenoci - Ueppy Technical Manager    
Via Piedo 58, 23020 Tresivio (SO)
+39 347 7196482
gia...@ueppy.com - http://www.ueppy.com/

Alessandro Marinuzzi

unread,
Oct 11, 2012, 4:54:45 AM10/11/12
to zb-p...@googlegroups.com
Il 11/10/2012 10:25, giovanni battista lenoci ha scritto:
La butto li perchè è da anni che non uso aruba, ma hai controllato anche il tempo di vita del cookie che conserva il session_id?

session.cookie_lifetime 0

comunque ecco cosa è impostato di default su aruba...

session.auto_start Off Off
session.bug_compat_42 On On
session.bug_compat_warn On On
session.cache_expire 180 180
session.cache_limiter nocache nocache
session.cookie_domain no value no value
session.cookie_lifetime 0 0
session.cookie_path / /
session.cookie_secure Off Off
session.entropy_file no value no value
session.entropy_length 0 0
session.gc_divisor 100 100
session.gc_maxlifetime 1440 1440
session.gc_probability 1 1
session.name PHPSESSID PHPSESSID
session.referer_check no value no value
session.save_handler files files
session.save_path /tmp /tmp
session.serialize_handler php php
session.use_cookies On On
session.use_only_cookies Off Off
session.use_trans_sid Off Off

Altre idee? Comunque grazie.

Ciao

--
Giovanni Battista Lenoci - Ueppy Technical Manager    
Via Piedo 58, 23020 Tresivio (SO)
+39 347 7196482
gia...@ueppy.com - http://www.ueppy.com/
--
Hai ricevuto questo messaggio perché sei iscritto al gruppo "zb-php-it" di Google Gruppi.
Per postare messaggi in questo gruppo, invia un'email a zb-p...@googlegroups.com.
Per annullare l'iscrizione a questo gruppo, invia un'email a zb-php-it+...@googlegroups.com.
Per ulteriori opzioni, visita il gruppo all'indirizzo http://groups.google.com/group/zb-php-it?hl=it.

Alessandro Marinuzzi

unread,
Oct 11, 2012, 5:26:31 AM10/11/12
to zb-p...@googlegroups.com
Il 11/10/2012 10:25, giovanni battista lenoci ha scritto:
La butto li perchè è da anni che non uso aruba, ma hai controllato anche il tempo di vita del cookie che conserva il session_id?

Ragazzi! Non so perché ma adesso aruba mi permette di sovrascrivere la durata di sessione :-)
Non capisco perché prima non funzionava e oggi si... che Aruba abbia qualche problema di memoria per cui si scorda che la sessione è impostata a 86400 * 5 ? :-P   La sessione è rimasta in piedi per 40 minuti senza scadere...

ini_set('session.gc_maxlifetime', 86400 * 5);
session_start();

Funziona... mi viene da chiedermi perché prima non funzionava lo stesso identico codice e adesso funziona... assurdo!!! >:o

Comunque adesso lascio la sessione attiva per tutto il giorno e vedo se è scaduta... cmq se ha superato tranquillamente i 40 minuti direi che il problema è risolto, poi i misteri del perché prima non funzionava e adesso si rimarrà come il terzo segreto di Fatima :-P

Grazie a tutti :-)



Ciao

--
Giovanni Battista Lenoci - Ueppy Technical Manager    
Via Piedo 58, 23020 Tresivio (SO)
+39 347 7196482
gia...@ueppy.com - http://www.ueppy.com/
--
Hai ricevuto questo messaggio perché sei iscritto al gruppo "zb-php-it" di Google Gruppi.
Per postare messaggi in questo gruppo, invia un'email a zb-p...@googlegroups.com.
Per annullare l'iscrizione a questo gruppo, invia un'email a zb-php-it+...@googlegroups.com.
Per ulteriori opzioni, visita il gruppo all'indirizzo http://groups.google.com/group/zb-php-it?hl=it.

Matteo Tinazzi

unread,
Oct 11, 2012, 5:38:35 AM10/11/12
to zb-p...@googlegroups.com
sei sicuro che sia così? controlla con un echo ini_get('session.gc_maxlifetime');

può essere che la sessione resti su anche per più del tempo stabilito nel session.gc_maxlifetime perchè il garbage collector non è detto che passi essendo probabilistico

session.gc_divisor 100 100
session.gc_probability 1 1

da come è impostato hai la probabilita di 1/100 che il garbage collector passi a buttare le sessioni scadute, il che si traduce che passa 1 volta ogni 100 pageview

se vuoi essere certo dovresti impostare il gc_probability = gc_divisor avendo così il garbage collector che passa ad ogni pageview, occhio però che se il sito è molto visitato potresti uccidere i dischi


Il 11/10/2012 11:26, Alessandro Marinuzzi ha scritto:
Ragazzi! Non so perché ma adesso aruba mi permette di sovrascrivere la durata di sessione :-)
Non capisco perché prima non funzionava e oggi si... che Aruba abbia qualche problema di memoria per cui si scorda che la sessione è impostata a 86400 * 5 ? :-P   La sessione è rimasta in piedi per 40 minuti senza scadere...

ini_set('session.gc_maxlifetime', 86400 * 5);
session_start();

Funziona... mi viene da chiedermi perché prima non funzionava lo stesso identico codice e adesso funziona... assurdo!!! >:o

Comunque adesso lascio la sessione attiva per tutto il giorno e vedo se è scaduta... cmq se ha superato tranquillamente i 40 minuti direi che il problema è risolto, poi i misteri del perché prima non funzionava e adesso si rimarrà come il terzo segreto di Fatima :-P

Grazie a tutti :-)


Cristiano Verondini

unread,
Oct 11, 2012, 5:44:51 AM10/11/12
to zb-p...@googlegroups.com

Mi sono un po' perso nella discussione, ma ricordate che sessione scaduta è diverso da file che contiene i dati di sessione cancellato. Ovviamente se il tempo di cancellazione è inferiore a quello della durata della sessione è quest'ultimo a vincere ...
-- 
Cristiano Verondini






Matteo Tinazzi

unread,
Oct 11, 2012, 5:50:39 AM10/11/12
to zb-p...@googlegroups.com
vero, che è il suo caso, infatti è il garbage collector a decidere quando la sessione scade avendo cookie_lifetime 0 e proprio per la sua natura probabilistica non è certo che allo scadere del gc_maxlifetime la sessione venga rimossa

Alessandro Marinuzzi

unread,
Oct 11, 2012, 8:47:14 AM10/11/12
to zb-p...@googlegroups.com
Il 11/10/2012 11:38, Matteo Tinazzi ha scritto:
sei sicuro che sia così? controlla con un echo ini_get('session.gc_maxlifetime');

può essere che la sessione resti su anche per più del tempo stabilito nel session.gc_maxlifetime perchè il garbage collector non è detto che passi essendo probabilistico

session.gc_divisor 100 100
session.gc_probability 1 1

da come è impostato hai la probabilita di 1/100 che il garbage collector passi a buttare le sessioni scadute, il che si traduce che passa 1 volta ogni 100 pageview

se vuoi essere certo dovresti impostare il gc_probability = gc_divisor avendo così il garbage collector che passa ad ogni pageview, occhio però che se il sito è molto visitato potresti uccidere i dischi

Come non detto... sto usando Ajax per aggiornare le sessioni perché con le seguenti impostazioni la sessione mi scade con puntualità millesimale dopo 20 minuti ed in ogni pagina avevo messo:

  ini_set('session.gc_maxlifetime', 86400 * 5);
  ini_set('session.gc_probability', 1);
  ini_set('session.gc_divisor', 1);
  ini_set('memory_limit', '-1');
  ini_set('register_globals', 0);
  ini_set('max_execution_time', 0);
  session_start();

Quindi il garbage collector ha fatto pulizia delle sessioni allo scadere dei 20 minuti esatti. Ho dovuto reimplementare chiamate asincrone Ajax per aggiornare i dati delle sessioni per altri 20 minuti. Con Ajax funziona tutto benissimo e penso che terrò tutto così. googlando ho trovato un tizio che scriveva che era una possibile alternativa disabilitare del tutto il GC per evitare che distrugga la sessione ma poi si presenterebbe il problema dei file di sessione non removibili perché nella cartella tmp del server... lo so è un accrocchio ma almeno funziona ed anche abbastanza bene. Grazie a tutti per i preziosi suggerimenti :-)

thair abdal

unread,
Oct 13, 2012, 4:51:29 AM10/13/12
to zb-p...@googlegroups.com
تحياتي لجميع الاصدقاء والصديقات

2012/10/11, Alessandro Marinuzzi <aleco...@libero.it>:

Alessandro Marinuzzi

unread,
Oct 13, 2012, 8:21:29 AM10/13/12
to zb-p...@googlegroups.com
Il 11/10/2012 09:03, Marcello Vezzelli ha scritto:
Purtroppo da me non posso sovrascrivere i valori del php.ini di aruba quindi ho optato per una cosa casareccia :-P

//=======================================//
// Commento unico con ID di 20 caratteri //
//=======================================//
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345689';
$length = 20;
$comment_id = '';
for ($i = 0; $i < $length; $i++) {
  $pos = mt_rand(0, strlen($chars) -1);
  $comment_id .= substr($chars, $pos, 1);
}
$cmid = $comment_id;
//============================================================// // Invio un cookie affinché il commento non sia duplicato // //============================================================// if ((!isset($_COOKIE['cmid'])) || (empty($_COOKIE['cmid']))) { setcookie('cmid', $cmid); $_COOKIE['cmid'] = $cmid; $cmid = $_COOKIE['cmid']; } else { $cmid = $_COOKIE['cmid']; }
quando l'utente termina di postare e conferma il commento elimino il cookie con

//===============================//
//  Distruggo Sessioni e Cookie  //
//===============================//
setcookie('cmid');
session_destroy();
Poi se l'utente re-inviare il commento producendo un duplicato dello stesso opero questo controllo

//============================================================//
//         Verifico che il commento non sia duplicato         //
//============================================================//
if ((!isset($_COOKIE['cmid'])) || (empty($_COOKIE['cmid']))) {
  include("double_commenti.php");
  exit();
}
Se il cookie è settato ed esiste allora non ha ancora postato, se invece il cookie non esiste perché confermando il commento è stato cancellato allora gli presento una pagina di errore che reindirizza l'utenze sulla root del mio sito (index.php)

e poi ho messo in ogni pagina per evitare il backward degli header che sconvalidano la pagina precedente che non risulta cached o stored e deve essere must-revalidate...

Ho così appurato che il cookie senza alcuna scadenza termina di vivere in presenza di due fattori:
1) il cookie viene cancellato perché il commento è già stato inviato
2) l'utente chiude il browser e quindi il cookie termina di esistere

Per cancellare il cookie mi è bastato invocarlo senza valori:

setcookie('cmid');

così è cancellato senza dover aggiungere date passate o altro...

Così ho scavalcato la durata delle sessioni di 20 minuti... con il cookie può restare collegato alla pagina sempre e non avrà la seccatura dei 20 minuti di sessione. Ho eliminato il codice Ajax ed il file keep-alive.php che rigenerava la sessione dopo 19 minuti.

PS: come riesci a impostare una sessione di 8 ore su aruba? hai un virtual host? Io ho il servizio base che mi costa 20 euro all'anno... + servizi aggiuntivi...

Comunque l'importante è che funzioni :-)
Reply all
Reply to author
Forward
0 new messages