Eu preciso manter uma sessão viva por 30 minutos e depois destruí-la.
Eu preciso manter uma sessão viva por 30 minutos e depois destruí-la.
Respostas:
Você deve implementar seu próprio tempo limite da sessão. Ambas as opções mencionadas por outras pessoas ( session.gc_maxlifetime e session.cookie_lifetime ) não são confiáveis. Eu vou explicar as razões para isso.
Primeiro:
session.gc_maxlifetime
session.gc_maxlifetime especifica o número de segundos após os quais os dados serão vistos como 'lixo' e limpos. A coleta de lixo ocorre durante o início da sessão.
Mas o coletor de lixo é iniciado apenas com uma probabilidade de session.gc_probability dividida por session.gc_divisor . E usando os valores padrão para essas opções (1 e 100 respectivamente), a chance é de apenas 1%.
Bem, você pode simplesmente ajustar esses valores para que o coletor de lixo seja iniciado com mais frequência. Mas quando o coletor de lixo é iniciado, ele verifica a validade de cada sessão registrada. E isso custa muito.
Além disso, ao usar os arquivos session.save_handler padrão do PHP , os dados da sessão são armazenados nos arquivos em um caminho especificado em session.save_path . Com esse manipulador de sessão, a idade dos dados da sessão é calculada na data da última modificação do arquivo e não na data do último acesso:
Nota: Se você estiver usando o manipulador de sessões baseado em arquivo padrão, seu sistema de arquivos deve acompanhar os tempos de acesso (atime). O Windows FAT não funciona, portanto você terá que criar outra maneira de lidar com a coleta de lixo da sua sessão, se você estiver com um sistema de arquivos FAT ou qualquer outro sistema de arquivos em que o rastreamento de atime não esteja disponível. Desde o PHP 4.2.3, ele usa mtime (data de modificação) em vez de atime. Portanto, você não terá problemas com sistemas de arquivos nos quais o atime tracking não está disponível.
Portanto, adicionalmente, pode ocorrer que um arquivo de dados da sessão seja excluído enquanto a própria sessão ainda é considerada válida porque os dados da sessão não foram atualizados recentemente.
E em segundo lugar:
session.cookie_lifetime
session.cookie_lifetime especifica o tempo de vida do cookie em segundos, que é enviado ao navegador. [...]
Sim está certo. Isso afeta apenas a vida útil do cookie e a própria sessão ainda pode ser válida. Mas é tarefa do servidor invalidar uma sessão, não o cliente. Então isso não ajuda em nada. De fato, ter session.cookie_lifetime definido como 0
tornaria o cookie da sessão um cookie de sessão real , válido apenas até o navegador ser fechado.
Conclusão / melhor solução:
A melhor solução é implementar seu próprio tempo limite de sessão. Use um registro de data e hora simples que indique a hora da última atividade (ou seja, solicitação) e atualize-a com cada solicitação:
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
A atualização dos dados da sessão com cada solicitação também altera a data de modificação do arquivo da sessão, para que a sessão não seja removida pelo coletor de lixo prematuramente.
Você também pode usar um carimbo de data / hora adicional para gerar novamente o ID da sessão periodicamente para evitar ataques a sessões como a fixação da sessão :
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
}
Notas:
session.gc_maxlifetime
deve ser pelo menos igual ao tempo de vida desse manipulador de expiração personalizado (1800 neste exemplo);setcookie
com um prazo de validade time()+60*30
para manter o cookie da sessão ativo.$_SESSION['LAST_ACTIVITY']
parecido com o local $_SESSION['CREATED']
onde você armazena o horário da última atividade do usuário, mas atualize esse valor a cada solicitação. Agora, se a diferença desse tempo para o tempo atual for maior que 1800 segundos, a sessão não será usada por mais de 30 minutos.
session_unset
faz o mesmo que $_SESSION = array()
.
ini_set('session.gc-maxlifetime', 1800)
? Caso contrário, as informações da sua sessão poderão ser destruídas enquanto a sua sessão ainda é válida, pelo menos se a configuração ini for o padrão de 24 minutos. Ou eu estou esquecendo de alguma coisa?
files
for usado. Portanto, session.gc_maxlifetime deve ser pelo menos igual ao tempo de vida desse manipulador de expiração personalizado.
Nota: se você quiser alterar a hora, basta alterar a 30 com a hora desejada e não altere * 60: isso fornecerá os minutos.
Em minutos: (30 * 60)
Em dias: (n * 24 * 60 * 60) n = não de dias
<?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
cabeçalhos são enviados APÓS o conteúdo, o que é ruim.
Isso é para desconectar o usuário após um tempo definido? Definir o tempo de criação da sessão (ou um tempo de expiração) quando ele é registrado e, em seguida, verificar se o carregamento de cada página pode lidar com isso.
Por exemplo:
$_SESSION['example'] = array('foo' => 'bar', 'registered' => time());
// later
if ((time() - $_SESSION['example']['registered']) > (60 * 30)) {
unset($_SESSION['example']);
}
Edit: Eu tenho a sensação de que você quer dizer outra coisa.
Você pode descartar sessões após uma certa vida útil, usando a session.gc_maxlifetime
configuração ini:
Edit: ini_set ('session.gc_maxlifetime', 60 * 30);
gc_maxlifetime
ou gc-maxlifetime
. Ele suporta sublinhados e hífens?
Esta postagem mostra algumas maneiras de controlar o tempo limite da sessão: http://bytes.com/topic/php/insights/889606-setting-timeout-php-sessions
IMHO a segunda opção é uma boa solução:
<?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);
}
}
Bem, eu entendo que as respostas acima estão corretas, mas estão no nível do aplicativo. Por que simplesmente não usamos o .htaccess
arquivo para definir o tempo de expiração?
<IfModule mod_php5.c>
#Session timeout
php_value session.cookie_lifetime 1800
php_value session.gc_maxlifetime 1800
</IfModule>
Use a função session_set_cookie_params
para fazer isso.
É necessário chamar esta função antes da session_start()
chamada.
Tente o seguinte:
$lifetime = strtotime('+30 minutes', 0);
session_set_cookie_params($lifetime);
session_start();
Veja mais em: http://php.net/manual/function.session-set-cookie-params.php
Na verdade, é fácil com uma função como a seguinte. Ele usa o nome da tabela de banco de dados 'sessões' com os campos 'id' e 'time'.
Sempre que o usuário visitar seu site ou serviço novamente, você deverá chamar esta função para verificar se o valor de retorno é VERDADEIRO. Se for FALSE, o usuário expirou e a sessão será destruída.
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;
}
Armazenar um carimbo de data / hora na sessão
<?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");
}
?>
Agora, verifique se o registro de data e hora está dentro da janela de tempo permitido (1800 segundos é 30 minutos)
<?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
}
?>
Use o seguinte bloco de código no seu arquivo de inclusão, carregado em todas as páginas.
$expiry = 1800 ;//session expiry required after 30 mins
if (isset($_SESSION['LAST']) && (time() - $_SESSION['LAST'] > $expiry)) {
session_unset();
session_destroy();
}
$_SESSION['LAST'] = time();
Use esta classe por 30 min
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");
}
}
Usando carimbo de data e hora ...
<?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>";
}
}
?>
Eu usei 20 segundos para expirar a sessão usando o carimbo de data / hora .
Se precisar de 30 min, adicione 1800 (30 min em segundos) ...
Você pode usar diretamente um banco de dados para fazer isso como uma alternativa. Eu uso uma função DB para fazer isso que chamo de chk_lgn.
Verifique as verificações de login para ver se elas estão conectadas ou não e, ao fazer isso, define o registro de data e hora da verificação como a última atividade na linha / coluna db do usuário.
Eu também faço a verificação do tempo lá. Isso funciona para mim no momento, pois uso essa função para todas as páginas.
PS: Ninguém que eu tinha visto sugerira uma solução pura de banco de dados.
Como o PHP lida com as sessões é bastante confuso para os iniciantes entenderem. Isso pode ajudá-los, fornecendo uma visão geral de como as sessões funcionam: como as sessões funcionam (manipuladores de sessão personalizados)
Apenas armazene o horário atual e, se exceder 30 minutos, comparando, destrua a sessão atual.