30 분 후에 PHP 세션을 어떻게 만료합니까?


1047

세션을 30 분 동안 유지 한 다음 파기해야합니다.


35
세션 시간을 설정하려면 적어도 두 가지 설정이 필요하며 세 가지 설정이 가능합니다. 확실히 중요한 두 가지는 session.gc_maxlifetime과 session.cookie_lifetime입니다 (여기서 0은 긴 숫자와 동일하지 않습니다). 완전한 100 % 확실성을 보장하기 위해 세션 파일이 기본적으로 저장되는 / tmp 디렉토리의 OS 제어 정리 시간이 다양하기 때문에 session.save_path를 설정해야 할 수도 있습니다.
Kzqai

1
세션을 만료하려는 이유를 모르겠습니다. 사용자가 로그 아웃하지 않고 자신의 컴퓨터를 떠날 것을 우려하고 권한이없는 사용자가 자신의 컴퓨터를 인계하더라도 사이트의 세션 만료로 인해 납치범이 디스크의 피해자 파일에 액세스하는 것을 막을 수 없습니다.
Gqqnbig

당신이 여기에 무엇을 묻고 있는지 확실하지 않습니다. 하드 비 활동 타임 아웃을 구현하길 원하십니까 (현재 PHP는 session.gc_maxlifetime 이상을 다루지 않은 세션을 행복하게 사용하도록 허용 함) 또는 무 활동? 솔직히 나는 여기서 받아 들인 대답이 두 가지 문제에 대한 나쁜 조언이라고 생각합니다. 두 경우 모두 논리는 사용자 정의 세션 처리기로 구현해야합니다.
symcbean 2019

답변:


1663

자신 만의 세션 시간 초과를 구현해야합니다. 다른 사람들이 언급 한 두 가지 옵션 ( session.gc_maxlifetimesession.cookie_lifetime )은 신뢰할 수 없습니다. 그 이유를 설명하겠습니다.

먼저:

session.gc_maxlifetime
session.gc_maxlifetime 은 데이터가 '쓰레기'로 표시되고 정리되는 시간 (초)을 지정합니다. 세션 시작 중에 가비지 콜렉션이 발생합니다.

그러나 가비지 컬렉터 만의 확률로 시작 session.gc_probability 로 나눈 session.gc_divisor는 . 이러한 옵션의 기본값 (각각 1과 100)을 사용하면 기회는 1 %에 불과합니다.

가비지 수집기가 더 자주 시작되도록 이러한 값을 간단히 조정할 수 있습니다. 그러나 가비지 수집기가 시작되면 등록 된 모든 세션의 유효성을 검사합니다. 그리고 그것은 비용 집약적입니다.

또한 PHP의 기본 session.save_handler 파일을 사용할 때 세션 데이터는 session.save_path에 지정된 경로의 파일에 저장됩니다 . 해당 세션 핸들러를 사용하면 세션 데이터의 수명이 마지막 액세스 날짜가 아니라 파일의 마지막 수정 날짜에 계산됩니다.

참고 : 기본 파일 기반 세션 핸들러를 사용하는 경우 파일 시스템은 액세스 시간을 추적해야합니다 (한 번). Windows FAT는 시간 추적을 사용할 수없는 FAT 파일 시스템 또는 다른 파일 시스템에 갇혀있는 경우 세션을 가비지 수집을 처리하는 다른 방법을 생각해 내야합니다. PHP 4.2.3부터는 atime 대신 mtime (수정 된 날짜)을 사용했습니다. 따라서 시간 추적을 사용할 수없는 파일 시스템에는 문제가 없습니다.

따라서 세션 데이터가 최근에 업데이트되지 않았기 때문에 세션 자체가 여전히 유효한 것으로 간주되는 동안 세션 데이터 파일이 삭제 될 수 있습니다.

그리고 두 번째 :

session.cookie_lifetime
session.cookie_lifetime 은 브라우저에 전송되는 쿠키 수명을 초 단위로 지정합니다. […]

네 맞습니다. 이는 쿠키 수명에만 영향을 미치며 세션 자체는 여전히 유효합니다. 그러나 클라이언트가 아닌 세션을 무효화하는 것은 서버의 작업입니다. 그래서 이것은 아무것도 도움이되지 않습니다. 실제로 session.cookie_lifetime을 설정하면 세션 쿠키 를 브라우저를 닫을 때까지만 유효한 0실제 세션 쿠키로 만들 수 있습니다.

결론 / 최상의 솔루션 :

가장 좋은 솔루션은 자신의 세션 시간 초과를 구현하는 것입니다. 마지막 활동 시간 (예 : 요청)을 나타내는 간단한 타임 스탬프를 사용하고 모든 요청으로 업데이트하십시오.

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

요청이있을 때마다 세션 데이터를 업데이트하면 가비지 수집기에서 세션이 조기에 제거되지 않도록 세션 파일의 수정 날짜도 변경됩니다.

세션 수정과 같은 세션 에 대한 공격을 피하기 위해 추가 타임 스탬프를 사용하여 세션 ID를 주기적으로 다시 생성 할 수도 있습니다 .

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)의 수명과 최소한 같아야합니다.
  • start 이후 30 분이 아닌 30 분 동안 활동 한 후 세션을 만료 하려면 세션 쿠키를 활성 상태로 유지하기 위해 만료와 함께 사용해야 합니다.setcookietime()+60*30

3
"비 활동 시간"을 확인하려면 어떻게 이것을 변경할 수 있습니까? 즉, 사용자는 로그인하며 사이트를 계속 사용하는 한 로그 아웃하지 않습니다. 그러나 30 분 동안 활동이 없으면 로그 아웃합니까?
메트로폴리스

14
@Metropolis : 사용자의 마지막 활동 시간을 저장하는 위치 와 $_SESSION['LAST_ACTIVITY']비슷한 것을 $_SESSION['CREATED']사용하지만 모든 요청마다 해당 값을 업데이트하십시오. 이 시간과 현재 시간의 차이가 1800 초보다 크면 세션이 30 분 이상 사용되지 않은 것입니다.
Gumbo

3
@Metropolis : session_unset와 동일합니다 $_SESSION = array().
Gumbo

14
@Gumbo-혼란 스러워요. 코드와 함께 사용하면 안되나요 ini_set('session.gc-maxlifetime', 1800)? 그렇지 않으면 최소한 ini 설정이 표준 24 분인 경우 세션이 유효해야하는 동안 세션 정보가 손상 될 수 있습니다. 아니면 뭔가 빠졌습니까?
jeroen

10
@ jeron : 예, 당신은해야합니다. 그러나 세션 저장 핸들러 가 사용되는 경우 session.gc_maxlifetime 은 파일의 마지막 수정 날짜에 따라 다릅니다 files. 따라서 session.gc_maxlifetime 은이 사용자 정의 만기 핸들러의 수명과 최소한 같아야합니다.
Gumbo

135

30 분 안에 간단한 PHP 세션 만료 방법.

참고 : 시간을 변경하려면 원하는 시간으로 30을 변경하고 * 60을 변경하지 마십시오. 분이 표시됩니다.


분 단위 : (30 * 60)
일 단위 : (n * 24 * 60 * 60) n = 일 수


Login.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
MVC가 표준 인 오늘날과 시대에는 논리와 표현의 결합이 잘못 권장됩니다.
bcosca

어쩌면 세션에 대한 기본 사항이 누락되었지만 OS가 세션을 30 분마다 파괴하면 어떻게됩니까?

25
@stillstanding 스스로 말하기 [미소] 나는 MVC를 가증 한 것으로 본다.

2
프로그래머가 한 명인 프로젝트가 작은 경우에도 MVC가 좋은 아이디어입니까? MVC 모델로 프로젝트를 직접 만들어야한다고 생각합니다 (또는 문제를 해결하여 MVC로 만듭니다). 그리고 해결책을 요구하는 초기 목표 / 문제에서 산만하다.
MrVimes

@ 여전히 언급해도 Login.php내용 에 따라 헤더 에서 헤더가 전송 된다는 것입니다 .
machineaddict

43

설정된 시간 후에 사용자를 로그 아웃합니까? 등록시 세션 작성 시간 (또는 만료 시간)을 설정 한 다음 각 페이지로드에서이를 처리 할 수 ​​있는지 확인하십시오.

예 :

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

// later

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

편집 : 나는 당신이 다른 것을 의미한다고 생각합니다.

session.gc_maxlifetimeini 설정 을 사용하여 특정 수명 후 세션을 폐기 할 수 있습니다 .

편집 : ini_set ( 'session.gc_maxlifetime', 60 * 30);


1
session.gc-maxlifetime이 가장 좋은 방법 일 것입니다.
Powerlord 2012

2
세션 쿠키 수명에는 몇 가지 문제가 있으며, 특히 쿠키를 적용하기 위해 클라이언트에 의존합니다. 쿠키 수명은 클라이언트가 쓸모 없거나 만료 된 쿠키를 정리할 수 있도록 해주 며, 보안과 관련된 어떤 것도 혼동해서는 안됩니다.
Jacco

그것은이다 gc_maxlifetimegc-maxlifetime. 밑줄과 하이픈을 모두 지원합니까?
Mike Causer

24

이 포스트는 세션 타임 아웃을 제어하는 ​​몇 가지 방법을 보여줍니다 : http://bytes.com/topic/php/insights/889606-setting-timeout-php-sessions

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

19

글쎄, 위의 답변이 정확하지만 응용 프로그램 수준에 있다는 것을 이해합니다. .htaccess파일을 사용하여 만료 시간을 설정 하지 않는 이유는 무엇입니까?

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

1
@Lode의 답변은이 답변이 신뢰할 수없는 이유를 완벽하게 설명합니다.
emix

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


11

실제로 다음과 같은 기능을 사용하면 쉽습니다. 'id'및 'time'필드와 함께 데이터베이스 테이블 이름 'sessions'를 사용합니다.

사용자가 사이트 나 서비스를 다시 방문 할 때마다이 함수를 호출하여 반환 값이 TRUE인지 확인해야합니다. 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;
}

9

세션에 타임 스탬프 저장


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

8

모든 페이지에로드 된 포함 파일에 다음 코드 블록을 사용하십시오.

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

1

이 수업을 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");
    }
}

0

타임 스탬프 사용 중 ...

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

timestamp 사용하여 20 초를 사용하여 세션을 만료했습니다 .

30 분이 필요한 경우 1800을 추가하십시오 (초당 30 분) ...


0

DB를 바로 사용하여 대안으로 사용할 수 있습니다. 나는 chk_lgn을 호출하기 위해 DB 함수를 사용합니다.

로그인 확인은 로그인 여부를 확인하여 로그인 할 때 사용자의 DB 행 / 열에서 마지막으로 활성화 된 것으로 확인 날짜 날짜를 설정합니다.

나는 또한 거기에서 시간을 확인합니다. 매 페이지 마다이 기능을 사용하는 동안 잠시 동안 작동합니다.

추신 : 내가 본 사람은 순수한 DB 솔루션을 제안하지 않았습니다.



-1

현재 시간 만 저장하고 비교하여 30 분을 초과하면 현재 세션을 삭제하십시오.


세션을 사용할 때만 평가할 때가 맞습니까?
Eric Kramer
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.