Làm cách nào để hết hạn một phiên PHP sau 30 phút?


1047

Tôi cần phải giữ một phiên sống trong 30 phút và sau đó phá hủy nó.


35
Xin lưu ý rằng ít nhất hai cài đặt là rất quan trọng để đặt thời gian phiên và có thể ba. Hai cái chắc chắn quan trọng là session.gc_maxlifetime và session.cookie_lifetime (trong đó 0 không giống với một số dài). Để hoàn thành, chắc chắn 100% cho phép thời gian dài, cũng có thể cần phải đặt session.save_path, do thời gian dọn dẹp được kiểm soát bởi hệ điều hành khác nhau trên thư mục / tmp nơi các tệp phiên được lưu trữ theo mặc định.
Kzqai

1
Tôi không hiểu tại sao bạn muốn hết hạn phiên. Nếu bạn lo lắng người dùng rời khỏi máy tính của mình mà không đăng xuất và người dùng trái phép chiếm quyền điều khiển máy tính của anh ta, việc hết hạn phiên trên trang web của bạn sẽ không ngăn chặn kẻ xâm nhập truy cập các tệp của nạn nhân trên đĩa.
Gqqnbig

Nó không rõ những gì bạn đang hỏi ở đây. Bạn có nghĩa là bạn muốn thực hiện thời gian chờ không hoạt động mạnh (hiện tại PHP sẽ vui vẻ cho phép bạn sử dụng phiên không được chạm nhiều hơn session.gc_maxlifetime) hoặc bạn có nghĩa là bạn muốn giới hạn phiên trong 30 phút bất kể không hoạt động? Thành thật mà nói tôi nghĩ rằng câu trả lời được chấp nhận ở đây là lời khuyên khá tệ cho một trong hai vấn đề - trong cả hai trường hợp, logic nên được thực hiện với một trình xử lý phiên tùy chỉnh.
symcbean

Câu trả lời:


1663

Bạn nên thực hiện một thời gian chờ phiên của riêng bạn. Cả hai tùy chọn được đề cập bởi những người khác ( session.gc_maxlifetimesession.cookie_lifetime ) đều không đáng tin cậy. Tôi sẽ giải thích lý do cho điều đó.

Đầu tiên:

session.gc_maxlifetime
session.gc_maxlifetime chỉ định số giây sau đó dữ liệu sẽ được xem là 'rác' và được dọn sạch. Thu gom rác xảy ra trong phiên bắt đầu.

Nhưng trình thu gom rác chỉ được bắt đầu với xác suất session.gc_probability chia cho session.gc_divisor . Và sử dụng các giá trị mặc định cho các tùy chọn đó (tương ứng 1 và 100), cơ hội chỉ ở mức 1%.

Chà, bạn có thể chỉ cần điều chỉnh các giá trị này để bộ thu gom rác được khởi động thường xuyên hơn. Nhưng khi bộ thu gom rác được khởi động, nó sẽ kiểm tra tính hợp lệ cho mỗi phiên đăng ký. Và đó là chi phí cao.

Hơn nữa, khi sử dụng các tệp session.save_handler mặc định của PHP , dữ liệu phiên được lưu trữ trong các tệp theo một đường dẫn được chỉ định trong session.save_path . Với trình xử lý phiên đó, tuổi của dữ liệu phiên được tính vào ngày sửa đổi cuối cùng của tệp và không phải là ngày truy cập cuối cùng:

Lưu ý: Nếu bạn đang sử dụng trình xử lý phiên dựa trên tệp mặc định, hệ thống tệp của bạn phải theo dõi thời gian truy cập (atime). Windows FAT không vì vậy bạn sẽ phải đưa ra một cách khác để xử lý rác thu thập phiên của bạn nếu bạn bị mắc kẹt với hệ thống tệp FAT hoặc bất kỳ hệ thống tệp nào khác không có tính năng theo dõi thời gian. Kể từ PHP 4.2.3, nó đã sử dụng mtime (ngày sửa đổi) thay vì atime. Vì vậy, bạn sẽ không gặp vấn đề với các hệ thống tập tin mà theo dõi atime không khả dụng.

Vì vậy, có thể xảy ra thêm rằng một tệp dữ liệu phiên bị xóa trong khi phiên vẫn được coi là hợp lệ vì dữ liệu phiên không được cập nhật gần đây.

Và thứ hai:

session.cookie_lifetime
session.cookie_lifetime chỉ định thời gian tồn tại của cookie trong vài giây được gửi tới trình duyệt. [Càng]

Vâng đúng vậy. Điều này chỉ ảnh hưởng đến tuổi thọ của cookie và bản thân phiên vẫn có thể hợp lệ. Nhưng đó là nhiệm vụ của máy chủ để vô hiệu hóa một phiên, không phải máy khách. Vì vậy, điều này không giúp được gì cả. Trên thực tế, việc đặt session.cookie_lifetime0 sẽ biến cookie của phiên thành cookie phiên thực sự chỉ có hiệu lực cho đến khi trình duyệt bị đóng.

Kết luận / giải pháp tốt nhất:

Giải pháp tốt nhất là thực hiện thời gian chờ phiên của riêng bạn. Sử dụng dấu thời gian đơn giản biểu thị thời gian của hoạt động cuối cùng (nghĩa là yêu cầu) và cập nhật nó với mọi yêu cầu:

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

Cập nhật dữ liệu phiên với mọi yêu cầu cũng thay đổi ngày sửa đổi của tệp phiên để phiên không bị xóa bởi trình thu gom rác sớm.

Bạn cũng có thể sử dụng dấu thời gian bổ sung để tạo lại ID phiên theo định kỳ để tránh các cuộc tấn công vào các phiên như sửa lỗi phiên :

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
}

Ghi chú:

  • session.gc_maxlifetime ít nhất phải bằng tuổi thọ của trình xử lý hết hạn tùy chỉnh này (1800 trong ví dụ này);
  • nếu bạn muốn hết hạn phiên sau 30 phút hoạt động thay vì sau 30 phút kể từ khi bắt đầu , bạn cũng cần sử dụng setcookiehết hạn time()+60*30để duy trì cookie phiên hoạt động.

3
Làm thế nào bạn có thể thay đổi điều này nếu bạn muốn kiểm tra "thời gian không hoạt động"? Nói cách khác, người dùng đăng nhập và miễn là họ tiếp tục sử dụng trang web, nó sẽ không đăng xuất. Tuy nhiên nếu họ không hoạt động trong 30 phút thì nó sẽ đăng xuất?
Thủ đô

14
@Metropolis: Sử dụng một cái gì đó $_SESSION['LAST_ACTIVITY']tương tự như $_SESSION['CREATED']nơi bạn lưu trữ thời gian của hoạt động cuối cùng của người dùng nhưng cập nhật giá trị đó với mỗi yêu cầu. Bây giờ nếu chênh lệch của thời gian đó với thời gian hiện tại lớn hơn 1800 giây, thì phiên không được sử dụng quá 30 phút.
Gumbo

3
@Metropolis: session_unsetkhông giống như $_SESSION = array().
Gumbo

14
@Gumbo - Tôi có chút bối rối, bạn có nên sử dụng mã của mình kết hợp với ini_set('session.gc-maxlifetime', 1800)không? Nếu không, thông tin phiên của bạn có thể bị hủy trong khi phiên của bạn vẫn được coi là hợp lệ, ít nhất là nếu cài đặt ini là 24 phút tiêu chuẩn. Hay tôi đang thiếu một cái gì đó?
jeroen

10
@jeron: Vâng, bạn nên. Nhưng lưu ý rằng session.gc_maxlifetime phụ thuộc vào ngày sửa đổi cuối cùng của tệp nếu trình xử lý lưu phiên filesđược sử dụng. Vì vậy, session.gc_maxlifetime ít nhất phải bằng thời gian sử dụng của trình xử lý hết hạn tùy chỉnh này.
Gumbo

135

Cách đơn giản của phiên PHP hết hạn trong 30 phút.

Lưu ý: nếu bạn muốn thay đổi thời gian, chỉ cần thay đổi 30 với thời gian bạn muốn và không thay đổi * 60: điều này sẽ cho số phút.


Trong phút: (30 * 60)
Trong ngày: (n * 24 * 60 * 60) n = không có ngày


Đăng nhập.php

<?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!";
        }
    }
?>

HomePage.php

<?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
        }
    }
?>

LogOut.php

<?php
    session_start();
    session_destroy();
    header('Location: http://localhost/somefolder/login.php');
?>

42
Kết hợp logic và trình bày là không được khuyến khích trong thời đại ngày nay khi MVC là chuẩn mực.
bcosca

Có thể tôi đang thiếu một cái gì đó cơ bản về các phiên nhưng điều này có ích gì nếu các phiên bị hệ điều hành phá hủy cứ sau 30 phút?

25
@still Hiểu Nói cho chính mình [cười] Tôi xem MVC là một sự gớm ghiếc.

2
MVC có phải là một ý tưởng tốt ngay cả khi dự án nhỏ, với một lập trình viên duy nhất không? Tôi cảm thấy mình nên thực hiện các dự án của riêng mình trong mô hình MVC (hoặc giải quyết vấn đề THEN làm cho nó thành MVC) nhưng với sự thiếu kinh nghiệm với MVC, nó chỉ trở thành một khối tinh thần "Làm thế nào để tôi tạo ra MVC này?" và một sự phân tâm từ mục tiêu / vấn đề ban đầu cần một giải pháp.
MrVimes

@still Hiểu một đề cập khác là trên Login.phpcác tiêu đề được gửi SAU nội dung, đó là xấu.
machineaddict

43

Đây có phải là để đăng xuất người dùng sau một thời gian thiết lập? Đặt thời gian tạo phiên (hoặc thời gian hết hạn) khi được đăng ký, sau đó kiểm tra xem trên mỗi lần tải trang có thể xử lý việc đó không.

Ví dụ:

$_SESSION['example'] = array('foo' => 'bar', 'registered' => time());

// later

if ((time() - $_SESSION['example']['registered']) > (60 * 30)) {
    unset($_SESSION['example']);
}

Chỉnh sửa: Tôi đã có một cảm giác bạn có ý nghĩa khác mặc dù.

Bạn có thể loại bỏ các phiên sau một tuổi thọ nhất định bằng cách sử dụng session.gc_maxlifetimecài đặt ini:

Chỉnh sửa: ini_set ('session.gc_maxlifetime', 60 * 30);


1
session.gc-maxlifetime có lẽ là cách tốt nhất để đi.
Powerlord

2
Có một số vấn đề với tuổi thọ cookie phiên, đáng chú ý nhất là nó phụ thuộc vào máy khách để thực thi nó. Thời gian tồn tại của cookie là ở đó để cho phép khách hàng dọn sạch các cookie vô dụng / đã hết hạn, không nên nhầm lẫn với bất kỳ điều gì liên quan đến bảo mật.
Jacco

Là nó gc_maxlifetimehay gc-maxlifetime. Nó có hỗ trợ cả dấu gạch dưới và dấu gạch ngang không?
Mike gây ra

24

Bài đăng này cho thấy một số cách kiểm soát thời gian chờ phiên: http://bytes.com/topic/php/insights/889606-setting-timeout-php-sairs

IMHO tùy chọn thứ hai là một giải pháp tốt đẹp:

<?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);
    }
}

19

Vâng, tôi hiểu câu trả lời của aboves là đúng nhưng chúng ở cấp độ ứng dụng, tại sao chúng ta không đơn giản sử dụng .htaccesstệp để đặt thời gian hết hạn?

<IfModule mod_php5.c>
    #Session timeout
    php_value session.cookie_lifetime 1800
    php_value session.gc_maxlifetime 1800
</IfModule>

1
Câu trả lời của @ Lode đưa ra lời giải thích hoàn hảo tại sao câu trả lời này không đáng tin cậy không nên được sử dụng.
emix

15
if (isSet($_SESSION['started'])){
    if((mktime() - $_SESSION['started'] - 60*30) > 0){
        //Logout, destroy session, etc.
    }
}
else {
    $_SESSION['started'] = mktime();
}


11

Nó thực sự dễ dàng với một chức năng như sau. Nó sử dụng tên bảng cơ sở dữ liệu 'phiên' với các trường 'id' và 'time'.

Mỗi khi người dùng truy cập lại trang web hoặc dịch vụ của bạn, bạn nên gọi hàm này để kiểm tra xem giá trị trả về của nó có ĐÚNG không. Nếu đó là FALSE, người dùng đã hết hạn và phiên sẽ bị hủy (Lưu ý: Hàm này sử dụng lớp cơ sở dữ liệu để kết nối và truy vấn cơ sở dữ liệu, tất nhiên bạn cũng có thể thực hiện bên trong chức năng của mình hoặc đại loại như thế):

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;
}

9

Lưu trữ dấu thời gian trong phiên


<?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");
}
?>

Bây giờ, Kiểm tra xem dấu thời gian có trong cửa sổ thời gian cho phép không (1800 giây là 30 phút)

<?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
}
?>

8

Vui lòng sử dụng khối mã sau trong tệp bao gồm của bạn được tải trong mỗi trang.

$expiry = 1800 ;//session expiry required after 30 mins
    if (isset($_SESSION['LAST']) && (time() - $_SESSION['LAST'] > $expiry)) {
        session_unset();
        session_destroy();
    }
    $_SESSION['LAST'] = time();

1

Sử dụng lớp này trong 30 phút

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");
    }
}

0

Sử dụng dấu thời gian ...

<?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>";
    }
}
?>

Tôi đã sử dụng 20 giây để hết hạn sử dụng dấu thời gian .

Nếu bạn cần 30 phút, hãy thêm 1800 (30 phút sau vài giây) ...


0

Bạn có thể sử dụng DB trực tiếp để thay thế. Tôi sử dụng hàm DB để làm điều đó mà tôi gọi là chk_lgn.

Kiểm tra kiểm tra đăng nhập để xem liệu chúng có được đăng nhập hay không và khi thực hiện, nó đặt dấu thời gian ngày của kiểm tra là hoạt động cuối cùng trong hàng / cột db của người dùng.

Tôi cũng làm kiểm tra thời gian ở đó. Điều này làm việc cho tôi vào lúc này khi tôi sử dụng chức năng này cho mỗi trang.

PS Không ai tôi từng thấy đã đề xuất một giải pháp DB thuần túy.



-1

Chỉ cần lưu trữ thời gian hiện tại và Nếu vượt quá 30 phút bằng cách so sánh thì hủy phiên hiện tại.


Lần duy nhất bạn đánh giá đó là khi sử dụng phiên, phải không?
Eric Kramer
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.