Мені потрібно тримати сеанс живим 30 хвилин, а потім знищити його.
Мені потрібно тримати сеанс живим 30 хвилин, а потім знищити його.
Відповіді:
Ви повинні реалізувати власний тайм-аут сеансу. Обидва варіанти, згадані іншими ( session.gc_maxlifetime та session.cookie_lifetime ), не є надійними. Я поясню причини цього.
Спочатку:
session.gc_maxlifetime
session.gc_maxlifetime визначає кількість секунд, після яких дані будуть розглядатися як "сміття" та очищатись. Збір сміття відбувається під час початку сеансу.
Але сміттєзбірник розпочинається лише з вірогідністю session.gc_probability, розділеною на session.gc_divisor . І використовуючи значення за замовчуванням для цих параметрів (1 і 100 відповідно), шанс становить лише 1%.
Ну, ви могли просто відрегулювати ці значення, щоб частіше запускати сміттєзбірник. Але коли запуститься сміттєзбірник, він перевірятиме дійсність для кожного зареєстрованого сеансу. І це затратно.
Крім того, при використанні файлів PHP за замовчуванням session.save_handler дані сеансу зберігаються у файлах шляхом, визначеним у session.save_path . За допомогою цього обробника сеансу вік даних сеансу обчислюється за останньою датою модифікації файлу, а не останньою датою доступу:
Примітка. Якщо ви використовуєте за замовчуванням файловий обробник сеансу, ваша файлова система повинна відслідковувати час доступу (atime). У Windows FAT це не так, що вам доведеться придумати інший спосіб поводження зі сміттям, збираючи сеанс, якщо ви застрягли з файловою системою FAT або будь-якою іншою файловою системою, де відстеження анімації недоступне. З PHP 4.2.3 він використовував mtime (модифіковану дату) замість atime. Таким чином, у вас не буде проблем з файловими системами, де відстеження atime недоступне.
Таким чином, додатково може статися, що файл даних сеансу видалено, тоді як сам сеанс все ще вважається дійсним, оскільки дані сеансу нещодавно не оновлювалися.
І друге:
session.cookie_lifetime
session.cookie_lifetime визначає тривалість файлу cookie в секундах, які надсилаються браузеру. […]
Так, правильно. Це впливає лише на час cookie, і сам сеанс може бути дійсним. Але завдання сервера - визнати недійсним сеанс, а не клієнта. Тож це нічого не допомагає. Насправді, встановлення сесії.cookie_lifetime0
зробить печиво сеансу справжнім сеансу файлом cookie сеансу, який діє лише до закриття браузера.
Висновок / найкраще рішення:
Найкраще рішення - реалізувати власний тайм-аут сеансу. Використовуйте просту позначку часу, яка позначає час останньої активності (тобто запиту) та оновлюйте її з кожним запитом:
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
Оновлення даних сеансу з кожним запитом також змінює дату зміни файлу сеансу, щоб сеанс не був видалений сміттєзбірником передчасно.
Ви також можете використовувати додаткову позначку часу для періодичного відновлення ідентифікатора сеансу, щоб уникнути атак на сеанси, як-от виправлення сеансу :
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
}
Примітки:
session.gc_maxlifetime
має бути принаймні рівним терміну експлуатації цього користувальницького терміну дії терміну дії (1800 у цьому прикладі);setcookie
терміном дії, time()+60*30
щоб зберегти cookie сеансу активним.$_SESSION['LAST_ACTIVITY']
подібне до того, $_SESSION['CREATED']
де ви зберігаєте час останньої активності користувача, але оновлюйте це значення з кожним запитом. Тепер, якщо відмінність цього часу від поточного часу перевищує 1800 секунд, сеанс не використовується більше 30 хвилин.
session_unset
робить те саме, що і $_SESSION = array()
.
ini_set('session.gc-maxlifetime', 1800)
? Інакше інформація про ваш сеанс може бути знищена, поки ваш сеанс все ще повинен бути дійсним, принаймні, якщо параметр ini є стандартним 24 хвилини. Або я щось пропускаю?
files
. Тож session.gc_maxlifetime має бути принаймні рівним терміну служби цього користувальницького терміну дії.
Примітка: якщо ви хочете змінити час, просто змініть 30 на потрібний час і не змінюйте * 60: це дасть хвилини.
У хвилинах: (30 * 60)
У днях: (n * 24 * 60 * 60) n = ні днів
<?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
заголовки надсилаються ПІСЛЯ вмісту, що погано.
Це для виходу користувача через встановлений час? Встановлення часу створення сеансу (або закінчення терміну дії) під час його реєстрації, а потім перевірки, чи може на цьому завантажуватися завантаження кожної сторінки.
Наприклад:
$_SESSION['example'] = array('foo' => 'bar', 'registered' => time());
// later
if ((time() - $_SESSION['example']['registered']) > (60 * 30)) {
unset($_SESSION['example']);
}
Редагувати: У мене є відчуття, що ти маєш на увазі щось інше.
Ви можете сканувати сеанси після певного періоду життя, використовуючи session.gc_maxlifetime
налаштування ini:
Редагувати: ini_set ('session.gc_maxlifetime', 60 * 30);
gc_maxlifetime
або gc-maxlifetime
. Чи підтримує це як підкреслення, так і дефіси?
У цій публікації показано кілька способів контролю затримки сеансу: http://bytes.com/topic/php/insights/889606-setting-timeout-php-sesions
IMHO другий варіант - хороше рішення:
<?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);
}
}
Добре, я розумію, що відповіді aboves правильні, але вони є на рівні програми, чому ми не просто використаємо .htaccess
файл для встановлення терміну придатності?
<IfModule mod_php5.c>
#Session timeout
php_value session.cookie_lifetime 1800
php_value session.gc_maxlifetime 1800
</IfModule>
Використовуйте функціонал session_set_cookie_params
для цього.
Потрібно викликати цю функцію раніше session_start()
викликом.
Спробуйте це:
$lifetime = strtotime('+30 minutes', 0);
session_set_cookie_params($lifetime);
session_start();
Детальніше дивіться в: http://php.net/manual/function.session-set-cookie-params.php
Насправді це легко з такою функцією, як наступна. Він використовує назву таблиці бази даних "сеанси" з полями "id" і "time".
Кожен раз, коли користувач знову відвідує ваш веб-сайт або послугу, ви повинні викликати цю функцію, щоб перевірити, чи є її повернене значення ІСТИНА. Якщо це FALSE, у користувача закінчився термін дії, і сеанс буде знищено (Примітка. Ця функція використовує клас бази даних для підключення та запиту бази даних; звичайно, ви також можете це зробити у своїй функції або щось подібне):
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;
}
Зберігати часову позначку в сеансі
<?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");
}
?>
Тепер перевірте, чи мітка часу знаходиться у межах дозволеного часового вікна (1800 секунд - 30 хвилин)
<?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
}
?>
Будь ласка, використовуйте наступний блок коду у вашому файлі включення, який завантажується на всі сторінки.
$expiry = 1800 ;//session expiry required after 30 mins
if (isset($_SESSION['LAST']) && (time() - $_SESSION['LAST'] > $expiry)) {
session_unset();
session_destroy();
}
$_SESSION['LAST'] = time();
Використовуйте цей клас протягом 30 хв
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");
}
}
Використання позначки часу ...
<?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>";
}
}
?>
Я використав 20 секунд, щоб закінчити сеанс за допомогою часової позначки .
Якщо вам потрібно 30 хв, додайте 1800 (30 хв за секунди) ...
Ви можете прямо використовувати БД, щоб зробити це як альтернативу. Для цього я використовую функцію БД, яку я називаю chk_lgn.
Перевірте чеки входу, щоб побачити, чи вони ввійшли чи ні, і при цьому він встановлює позначку часу дати перевірки як останню активну в рядку / стовпці db користувача.
Я також там перевіряю час. Це працює для мене на даний момент, оскільки я використовую цю функцію для кожної сторінки.
PS Ніхто, кого я бачив, не пропонував чистого рішення БД.
Те, як PHP обробляє сеанси, доволі заплутане для початківців. Це може допомогти їм, подавши огляд того, як працюють сесії: як працюють сеанси (користувальницькі сесії)
Просто збережіть поточний час і якщо він перевищує 30 хвилин, порівнюючи, тоді знищити поточний сеанс.