Devo mantenere viva una sessione per 30 minuti e poi distruggerla.
Devo mantenere viva una sessione per 30 minuti e poi distruggerla.
Risposte:
È necessario implementare un timeout di sessione autonomo. Entrambe le opzioni menzionate da altri ( session.gc_maxlifetime e session.cookie_lifetime ) non sono affidabili. Spiegherò le ragioni di ciò.
Primo:
session.gc_maxlifetime
session.gc_maxlifetime specifica il numero di secondi dopo i quali i dati saranno visti come "immondizia" e ripuliti. La garbage collection si verifica all'avvio della sessione.
Ma il Garbage Collector viene avviato solo con una probabilità di session.gc_probability divisa per session.gc_divisor . E usando i valori predefiniti per quelle opzioni (rispettivamente 1 e 100), la probabilità è solo dell'1%.
Bene, potresti semplicemente regolare questi valori in modo che il Garbage Collector venga avviato più spesso. Ma quando viene avviato il Garbage Collector, verificherà la validità di ogni sessione registrata. E questo è costoso.
Inoltre, quando si utilizzano i file session.save_handler predefiniti di PHP , i dati della sessione vengono archiviati in file in un percorso specificato in session.save_path . Con quel gestore di sessione, l'età dei dati della sessione viene calcolata sull'ultima data di modifica del file e non sull'ultima data di accesso:
Nota: se si utilizza il gestore di sessioni basato su file predefinito, il file system deve tenere traccia dei tempi di accesso (atime). Windows FAT non è così, dovrai trovare un altro modo per gestire la raccolta di dati inutili della sessione se sei bloccato con un file system FAT o qualsiasi altro file system in cui il monitoraggio atime non è disponibile. Da PHP 4.2.3 ha usato mtime (data modificata) anziché atime. Quindi, non avrai problemi con i filesystem in cui il monitoraggio atime non è disponibile.
Quindi potrebbe anche accadere che un file di dati di sessione venga eliminato mentre la sessione stessa è ancora considerata valida perché i dati della sessione non sono stati aggiornati di recente.
E secondo:
session.cookie_lifetime
session.cookie_lifetime specifica la durata del cookie in secondi che viene inviato al browser. [...]
Sì, è giusto. Ciò influisce solo sulla durata dei cookie e la sessione stessa potrebbe essere ancora valida. Ma è compito del server invalidare una sessione, non il client. Quindi questo non aiuta nulla. In effetti, avere session.cookie_lifetime impostato su 0
renderebbe il cookie della sessione un vero cookie di sessione valido solo fino alla chiusura del browser.
Conclusione / migliore soluzione:
La soluzione migliore è implementare un timeout di sessione personalizzato. Utilizzare un semplice timestamp che indica l'ora dell'ultima attività (ad es. Richiesta) e aggiornarla ad ogni richiesta:
if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > 1800)) {
// last request was more than 30 minutes ago
session_unset(); // unset $_SESSION variable for the run-time
session_destroy(); // destroy session data in storage
}
$_SESSION['LAST_ACTIVITY'] = time(); // update last activity time stamp
L'aggiornamento dei dati della sessione con ogni richiesta modifica anche la data di modifica del file della sessione in modo che la sessione non venga rimossa prematuramente dal Garbage Collector.
È inoltre possibile utilizzare un timestamp aggiuntivo per rigenerare periodicamente l'ID sessione per evitare attacchi a sessioni come la fissazione della sessione :
if (!isset($_SESSION['CREATED'])) {
$_SESSION['CREATED'] = time();
} else if (time() - $_SESSION['CREATED'] > 1800) {
// session started more than 30 minutes ago
session_regenerate_id(true); // change session ID for the current session and invalidate old session ID
$_SESSION['CREATED'] = time(); // update creation time
}
Appunti:
session.gc_maxlifetime
dovrebbe essere almeno uguale alla durata di questo gestore di scadenza personalizzato (1800 in questo esempio);setcookie
una scadenza time()+60*30
per mantenere attivo il cookie di sessione.$_SESSION['LAST_ACTIVITY']
simile a $_SESSION['CREATED']
dove memorizzi l'ora dell'ultima attività dell'utente ma aggiorni quel valore con ogni richiesta. Ora se la differenza tra quell'ora e l'ora corrente è maggiore di 1800 secondi, la sessione non è stata utilizzata per più di 30 minuti.
session_unset
fa lo stesso di $_SESSION = array()
.
ini_set('session.gc-maxlifetime', 1800)
? Altrimenti le informazioni sulla sessione potrebbero essere distrutte mentre la sessione dovrebbe essere ancora valida, almeno se l'impostazione ini è i 24 minuti standard. Oppure mi sfugge qualcosa?
files
viene utilizzato il gestore di salvataggio della sessione . Quindi session.gc_maxlifetime dovrebbe essere almeno uguale al tempo di vita di questo gestore di scadenza personalizzato.
Nota: se si desidera modificare l'ora, basta cambiare il 30 con l'ora desiderata e non cambiare * 60: questo darà i minuti.
In minuti: (30 * 60)
In giorni: (n * 24 * 60 * 60) n = no di giorni
<?php
session_start();
?>
<html>
<form name="form1" method="post">
<table>
<tr>
<td>Username</td>
<td><input type="text" name="text"></td>
</tr>
<tr>
<td>Password</td>
<td><input type="password" name="pwd"></td>
</tr>
<tr>
<td><input type="submit" value="SignIn" name="submit"></td>
</tr>
</table>
</form>
</html>
<?php
if (isset($_POST['submit'])) {
$v1 = "FirstUser";
$v2 = "MyPassword";
$v3 = $_POST['text'];
$v4 = $_POST['pwd'];
if ($v1 == $v3 && $v2 == $v4) {
$_SESSION['luser'] = $v1;
$_SESSION['start'] = time(); // Taking now logged in time.
// Ending a session in 30 minutes from the starting time.
$_SESSION['expire'] = $_SESSION['start'] + (30 * 60);
header('Location: http://localhost/somefolder/homepage.php');
} else {
echo "Please enter the username or password again!";
}
}
?>
<?php
session_start();
if (!isset($_SESSION['luser'])) {
echo "Please Login again";
echo "<a href='http://localhost/somefolder/login.php'>Click Here to Login</a>";
}
else {
$now = time(); // Checking the time now when home page starts.
if ($now > $_SESSION['expire']) {
session_destroy();
echo "Your session has expired! <a href='http://localhost/somefolder/login.php'>Login here</a>";
}
else { //Starting this else one [else1]
?>
<!-- From here all HTML coding can be done -->
<html>
Welcome
<?php
echo $_SESSION['luser'];
echo "<a href='http://localhost/somefolder/logout.php'>Log out</a>";
?>
</html>
<?php
}
}
?>
<?php
session_start();
session_destroy();
header('Location: http://localhost/somefolder/login.php');
?>
Login.php
intestazioni vengono inviati DOPO il contenuto, il che è male.
Questo per disconnettere l'utente dopo un tempo prestabilito? L'impostazione del tempo di creazione della sessione (o un tempo di scadenza) quando è registrato, e quindi il controllo che su ogni caricamento della pagina potrebbe gestirlo.
Per esempio:
$_SESSION['example'] = array('foo' => 'bar', 'registered' => time());
// later
if ((time() - $_SESSION['example']['registered']) > (60 * 30)) {
unset($_SESSION['example']);
}
Modifica: ho la sensazione che intendi qualcos'altro però.
Puoi eliminare le sessioni dopo una certa durata utilizzando l' session.gc_maxlifetime
impostazione INI:
Modifica: ini_set ('session.gc_maxlifetime', 60 * 30);
gc_maxlifetime
o gc-maxlifetime
. Supporta sia trattini bassi che trattini?
Questo post mostra un paio di modi per controllare il timeout della sessione: http://bytes.com/topic/php/insights/889606-setting-timeout-php-sessions
IMHO la seconda opzione è una bella soluzione:
<?php
/***
* Starts a session with a specific timeout and a specific GC probability.
* @param int $timeout The number of seconds until it should time out.
* @param int $probability The probablity, in int percentage, that the garbage
* collection routine will be triggered right now.
* @param strint $cookie_domain The domain path for the cookie.
*/
function session_start_timeout($timeout=5, $probability=100, $cookie_domain='/') {
// Set the max lifetime
ini_set("session.gc_maxlifetime", $timeout);
// Set the session cookie to timout
ini_set("session.cookie_lifetime", $timeout);
// Change the save path. Sessions stored in teh same path
// all share the same lifetime; the lowest lifetime will be
// used for all. Therefore, for this to work, the session
// must be stored in a directory where only sessions sharing
// it's lifetime are. Best to just dynamically create on.
$seperator = strstr(strtoupper(substr(PHP_OS, 0, 3)), "WIN") ? "\\" : "/";
$path = ini_get("session.save_path") . $seperator . "session_" . $timeout . "sec";
if(!file_exists($path)) {
if(!mkdir($path, 600)) {
trigger_error("Failed to create session save path directory '$path'. Check permissions.", E_USER_ERROR);
}
}
ini_set("session.save_path", $path);
// Set the chance to trigger the garbage collection.
ini_set("session.gc_probability", $probability);
ini_set("session.gc_divisor", 100); // Should always be 100
// Start the session!
session_start();
// Renew the time left until this session times out.
// If you skip this, the session will time out based
// on the time when it was created, rather than when
// it was last used.
if(isset($_COOKIE[session_name()])) {
setcookie(session_name(), $_COOKIE[session_name()], time() + $timeout, $cookie_domain);
}
}
Bene capisco che le risposte di aboves sono corrette ma sono a livello di applicazione, perché non usiamo semplicemente il .htaccess
file per impostare il tempo di scadenza?
<IfModule mod_php5.c>
#Session timeout
php_value session.cookie_lifetime 1800
php_value session.gc_maxlifetime 1800
</IfModule>
Usa la session_set_cookie_params
funzione per farlo.
È necessario chiamare prima questa funzione session_start()
chiamare.
Prova questo:
$lifetime = strtotime('+30 minutes', 0);
session_set_cookie_params($lifetime);
session_start();
Vedi di più in: http://php.net/manual/function.session-set-cookie-params.php
In realtà è facile con una funzione come la seguente. Utilizza il nome della tabella del database 'sessioni' con i campi 'id' e 'time'.
Ogni volta che l'utente visita nuovamente il tuo sito o servizio, dovresti invocare questa funzione per verificare se il suo valore di ritorno è VERO. Se è FALSO l'utente è scaduto e la sessione verrà distrutta (Nota: questa funzione utilizza una classe di database per connettersi e interrogare il database, ovviamente potresti farlo anche all'interno della tua funzione o qualcosa del genere):
function session_timeout_ok() {
global $db;
$timeout = SESSION_TIMEOUT; //const, e.g. 6 * 60 for 6 minutes
$ok = false;
$session_id = session_id();
$sql = "SELECT time FROM sessions WHERE session_id = '".$session_id."'";
$rows = $db->query($sql);
if ($rows === false) {
//Timestamp could not be read
$ok = FALSE;
}
else {
//Timestamp was read succesfully
if (count($rows) > 0) {
$zeile = $rows[0];
$time_past = $zeile['time'];
if ( $timeout + $time_past < time() ) {
//Time has expired
session_destroy();
$sql = "DELETE FROM sessions WHERE session_id = '" . $session_id . "'";
$affected = $db -> query($sql);
$ok = FALSE;
}
else {
//Time is okay
$ok = TRUE;
$sql = "UPDATE sessions SET time='" . time() . "' WHERE session_id = '" . $session_id . "'";
$erg = $db -> query($sql);
if ($erg == false) {
//DB error
}
}
}
else {
//Session is new, write it to database table sessions
$sql = "INSERT INTO sessions(session_id,time) VALUES ('".$session_id."','".time()."')";
$res = $db->query($sql);
if ($res === FALSE) {
//Database error
$ok = false;
}
$ok = true;
}
return $ok;
}
return $ok;
}
Memorizza un timestamp nella sessione
<?php
$user = $_POST['user_name'];
$pass = $_POST['user_pass'];
require ('db_connection.php');
// Hey, always escape input if necessary!
$result = mysql_query(sprintf("SELECT * FROM accounts WHERE user_Name='%s' AND user_Pass='%s'", mysql_real_escape_string($user), mysql_real_escape_string($pass));
if( mysql_num_rows( $result ) > 0)
{
$array = mysql_fetch_assoc($result);
session_start();
$_SESSION['user_id'] = $user;
$_SESSION['login_time'] = time();
header("Location:loggedin.php");
}
else
{
header("Location:login.php");
}
?>
Ora, controlla se il timestamp rientra nella finestra temporale consentita (1800 secondi è 30 minuti)
<?php
session_start();
if( !isset( $_SESSION['user_id'] ) || time() - $_SESSION['login_time'] > 1800)
{
header("Location:login.php");
}
else
{
// uncomment the next line to refresh the session, so it will expire after thirteen minutes of inactivity, and not thirteen minutes after login
//$_SESSION['login_time'] = time();
echo ( "this session is ". $_SESSION['user_id'] );
//show rest of the page and all other content
}
?>
Utilizzare il seguente blocco di codice nel file include che è stato caricato in ogni pagina.
$expiry = 1800 ;//session expiry required after 30 mins
if (isset($_SESSION['LAST']) && (time() - $_SESSION['LAST'] > $expiry)) {
session_unset();
session_destroy();
}
$_SESSION['LAST'] = time();
Usa questa lezione per 30 minuti
class Session{
public static function init(){
ini_set('session.gc_maxlifetime', 1800) ;
session_start();
}
public static function set($key, $val){
$_SESSION[$key] =$val;
}
public static function get($key){
if(isset($_SESSION[$key])){
return $_SESSION[$key];
} else{
return false;
}
}
public static function checkSession(){
self::init();
if(self::get("adminlogin")==false){
self::destroy();
header("Location:login.php");
}
}
public static function checkLogin(){
self::init();
if(self::get("adminlogin")==true){
header("Location:index.php");
}
}
public static function destroy(){
session_destroy();
header("Location:login.php");
}
}
Utilizzo del timestamp ...
<?php
if (!isset($_SESSION)) {
$session = session_start();
}
if ($session && !isset($_SESSION['login_time'])) {
if ($session == 1) {
$_SESSION['login_time']=time();
echo "Login :".$_SESSION['login_time'];
echo "<br>";
$_SESSION['idle_time']=$_SESSION['login_time']+20;
echo "Session Idle :".$_SESSION['idle_time'];
echo "<br>";
} else{
$_SESSION['login_time']="";
}
} else {
if (time()>$_SESSION['idle_time']){
echo "Session Idle :".$_SESSION['idle_time'];
echo "<br>";
echo "Current :".time();
echo "<br>";
echo "Session Time Out";
session_destroy();
session_unset();
} else {
echo "Logged In<br>";
}
}
?>
Ho usato 20 secondi per scadere la sessione usando il timestamp .
Se hai bisogno di 30 minuti aggiungi 1800 (30 minuti in secondi) ...
Puoi usare direttamente un DB per farlo in alternativa. Uso una funzione DB per farlo che chiamo chk_lgn.
Controlla i controlli di accesso per vedere se sono connessi o meno e, in tal modo, imposta il timestamp della data dell'assegno come ultimo attivo nella riga / colonna del db dell'utente.
Faccio anche il controllo del tempo lì. Questo funziona per me per il momento in quanto utilizzo questa funzione per ogni pagina.
PS Nessuno di quelli che avevo visto aveva suggerito una soluzione DB pura.
Il modo in cui PHP gestisce le sessioni è piuttosto confuso per i principianti. Questo potrebbe aiutarli fornendo una panoramica di come funzionano le sessioni: come funzionano le sessioni (gestori di sessioni personalizzate)
Memorizza solo l'ora corrente e se supera i 30 minuti confrontando, distruggi la sessione corrente.