Hướng dẫn session timeout php - thời gian chờ phiên php

Nếu bạn sử dụng xử lý phiên mặc định của PHP, cách duy nhất để thay đổi đáng tin cậy thời lượng phiên trong tất cả các nền tảng là thay đổi php.ini. Đó là bởi vì trong một số nền tảng, bộ sưu tập rác được triển khai thông qua một tập lệnh chạy mọi thời điểm nhất định (một tập lệnh cron) đọc trực tiếp từ php.ini, và do đó, bất kỳ nỗ lực nào trong việc thay đổi nó trong thời gian chạy, ví dụ: Thông qua ini_set(), không đáng tin cậy và rất có thể sẽ không hoạt động.

Ví dụ, trong các hệ thống Linux Debian, bộ sưu tập rác bên trong của PHP bị vô hiệu hóa bằng cách đặt session.gc_probability=0 theo mặc định trong cấu hình và thay vào đó được thực hiện thông qua /etc/cron.d/php, chạy tại XX: 09 và XX: 39 (nghĩa là , mỗi nửa giờ). Công việc cron này tìm kiếm các phiên cũ hơn so với phiên.gc_maxlifetime được chỉ định trong cấu hình và nếu có được tìm thấy, chúng sẽ bị xóa. Kết quả là, trong các hệ thống này ini_set('session.gc_maxlifetime', ...) bị bỏ qua. Điều đó cũng giải thích lý do tại sao trong câu hỏi này: Phiên PHP quá nhanh, OP có vấn đề trong một máy chủ nhưng các vấn đề đã chấm dứt khi chuyển sang một máy chủ khác.session.gc_maxlifetime specified in the configuration, and if any are found, they are deleted. As a consequence, in these systems ini_set('session.gc_maxlifetime', ...) is ignored. That also explains why in this question: PHP sessions timing out too quickly, the OP had problems in one host but the problems ceased when switching to a different host.

Vì vậy, cho rằng bạn không có quyền truy cập vào php.ini, nếu bạn muốn thực hiện nó một cách vô lý, sử dụng xử lý phiên mặc định không phải là một tùy chọn. Rõ ràng, việc mở rộng tuổi thọ cookie là đủ cho máy chủ của bạn, nhưng nếu bạn muốn một giải pháp hoạt động đáng tin cậy ngay cả khi bạn chuyển đổi máy chủ, bạn phải sử dụng một giải pháp thay thế khác.

Các phương pháp thay thế có sẵn bao gồm:

  1. Đặt trình xử lý phiên (lưu) khác trong PHP để lưu các phiên của bạn trong một thư mục khác hoặc trong cơ sở dữ liệu, như được chỉ định trong Php: Trình xử lý phiên tùy chỉnh (Hướng dẫn sử dụng PHP), để công việc cron không đạt đến và chỉ PHP của PHP không đạt được và chỉ Bộ sưu tập rác nội bộ diễn ra. Tùy chọn này có thể có thể sử dụng ini_set() để đặt phiên.gc_maxlifetime nhưng tôi thích bỏ qua tham số MaxLifetime trong cuộc gọi lại gc() của tôi và tự mình xác định tuổi thọ tối đa.session.gc_maxlifetime but I prefer to just ignore the maxlifetime parameter in my gc() callback and determine maximum lifetime on my own.

  2. Hoàn toàn quên mất việc xử lý phiên nội bộ PHP và thực hiện quản lý phiên của riêng bạn. Phương pháp này có hai nhược điểm chính: bạn sẽ cần các biến phiên toàn cầu của riêng mình, vì vậy bạn mất lợi thế của Superglobal $_SESSION và nó cần nhiều mã hơn do đó có nhiều cơ hội hơn cho lỗi và lỗ hổng bảo mật. Quan trọng nhất, số nhận dạng phiên nên được tạo ra từ các số giả hoặc giả ngẫu nhiên bảo mật bằng mã hóa để tránh dự đoán ID phiên (dẫn đến vụ cướp phiên có thể) và điều đó không dễ thực hiện với PHP một cách một cách rõ ràng. Ưu điểm chính là nó sẽ hoạt động nhất quán trong tất cả các nền tảng và bạn có toàn quyền kiểm soát mã. Đó là cách tiếp cận được thực hiện, ví dụ: bởi phần mềm diễn đàn PHPBB (ít nhất là phiên bản 1; Tôi không chắc chắn về các phiên bản gần đây hơn).

Có một ví dụ về (1) trong tài liệu cho session_set_save_handler(). Ví dụ dài nhưng tôi sẽ sao chép nó ở đây, với các sửa đổi có liên quan cần thiết để kéo dài thời lượng phiên. Lưu ý sự bao gồm của session_set_cookie_params() để tăng tuổi thọ cookie.

savePath = 'my_savepath'; // Ignore savepath and use our own to keep it safe from automatic GC
        $this->lifetime = 3600; // 1 hour minimum session duration
        if (!is_dir($this->savePath)) {
            mkdir($this->savePath, 0777);
        }

        return true;
    }

    function close()
    {
        return true;
    }

    function read($id)
    {
        return (string)@file_get_contents("$this->savePath/sess_$id");
    }

    function write($id, $data)
    {
        return file_put_contents("$this->savePath/sess_$id", $data) === false ? false : true;
    }

    function destroy($id)
    {
        $file = "$this->savePath/sess_$id";
        if (file_exists($file)) {
            unlink($file);
        }

        return true;
    }

    function gc($maxlifetime)
    {
        foreach (glob("$this->savePath/sess_*") as $file) {
            if (filemtime($file) + $this->lifetime < time() && file_exists($file)) { // Use our own lifetime
                unlink($file);
            }
        }

        return true;
    }
}

$handler = new FileSessionHandler();
session_set_save_handler(
    array($handler, 'open'),
    array($handler, 'close'),
    array($handler, 'read'),
    array($handler, 'write'),
    array($handler, 'destroy'),
    array($handler, 'gc')
    );

// the following prevents unexpected effects when using objects as save handlers
register_shutdown_function('session_write_close');

session_set_cookie_params(3600); // Set session cookie duration to 1 hour
session_start();
// proceed to set and retrieve values by key from $_SESSION

Cách tiếp cận (2) phức tạp hơn; Về cơ bản, bạn phải tự mình thực hiện lại tất cả các chức năng phiên. Tôi sẽ không đi vào chi tiết ở đây.