PHP에서 세션 시간 초과를 변경하는 방법은 무엇입니까?


154

PHP에서 세션 시간 초과를 연장하고 싶습니다

php.ini 파일을 수정하면 가능하다는 것을 알고 있습니다. 그러나 나는 그것에 접근 할 수 없다.

PHP 코드로만 할 수 있습니까?



1
관련, 이것은 php.ini에 있지만, @matino와 같이 ini_set을 사용할 수 있다고 생각합니다. stackoverflow.com/questions/520237/…
J-Rou

답변:


324

세션 타임 아웃은 엄격한 보증을 원한다면 코드로 구현되어야하는 개념입니다. 이것이 X 분 동안 활동이 없으면 세션이 지속되지 않을 것이라는 확신을 가질 수있는 유일한 방법 입니다.

이 요구 사항을 약간 완화하는 것이 허용되며 기간에 엄격한 제한 대신 하한 을 두는 것이 좋으면 사용자 지정 논리를 작성하지 않고도 쉽게 할 수 있습니다.

편안한 환경에서의 편리함 : 방법과 이유

경우 사용자의 세션이 (그들은 아마도) 쿠키로 구현되며, 경우 클라이언트가 악의적이지, 당신이 설정할 수 있습니다 상위 특정 매개 변수를 조정하여 세션 기간에 바인딩됩니다. 쿠키와 함께 PHP의 기본 세션 처리를 사용하는 경우 다음 session.gc_maxlifetime과 같이 설정 session_set_cookie_params하면 작동합니다.

// server should keep session data for AT LEAST 1 hour
ini_set('session.gc_maxlifetime', 3600);

// each client should remember their session id for EXACTLY 1 hour
session_set_cookie_params(3600);

session_start(); // ready to go!

이 기능은 최소 1 시간 동안 비활성 상태로 세션 데이터를 유지하도록 서버를 구성하고 클라이언트에게 동일한 시간 범위 후에 세션 ID를 "잊어 버려야"한다고 지시합니다. 예상 결과를 얻으려면이 두 단계가 모두 필요합니다.

  • 한 시간 후에 클라이언트에게 세션 ID를 잊도록 지시하지 않으면 (또는 클라이언트가 악의적이며 지침을 무시하도록 선택한 경우) 동일한 세션 ID를 계속 사용하며 유효 기간은 결정적이지 않습니다. 서버 측에서 수명이 만료 된 세션은 즉시 가비지 수집되지 않고 세션 GC가 시작될 때마다 가비지 수집되기 때문 입니다 .

    GC는 잠재적으로 비용이 많이 드는 프로세스이므로 일반적으로 확률은 다소 적거나 0입니다 (많은 적중 횟수를 얻은 웹 사이트는 아마도 확률 적 GC를 포기하고 매 X 분마다 백그라운드에서 발생하도록 예약합니다). 두 경우 모두 (비 협력 클라이언트 가정) 유효 세션 수명에 대한 session.gc_maxlifetime하한은이지만 상한은 예측할 수 없습니다.

  • session.gc_maxlifetime동일한 시간 범위로 설정하지 않으면 서버는 그 이전의 유휴 세션 데이터를 버릴 수 있습니다. 이 경우 여전히 세션 ID를 기억하는 클라이언트는 세션 ID를 표시하지만 서버는 해당 세션과 연관된 데이터를 찾지 못하므로 세션이 방금 시작된 것처럼 효과적으로 작동합니다.

중요한 환경에서의 확실성

사용자 지정 논리를 사용하여 세션 비 활동에 상한을 두어 사물을 완전히 제어 할 수 있습니다 . 위의 하한과 함께이 설정은 엄격하게 설정됩니다.

나머지 세션 데이터와 함께 상한을 저장하여이를 수행하십시오.

session_start(); // ready to go!

$now = time();
if (isset($_SESSION['discard_after']) && $now > $_SESSION['discard_after']) {
    // this session has worn out its welcome; kill it and start a brand new one
    session_unset();
    session_destroy();
    session_start();
}

// either new or old, it should live at most for another hour
$_SESSION['discard_after'] = $now + 3600;

세션 ID 지속성

지금까지 우리는 각 세션 ID의 정확한 값에 전혀 관심이 없었으며 필요한만큼 데이터가 존재해야한다는 요구 사항 만있었습니다. (아마도) 세션 ID가 중요한 경우, session_regenerate_id필요할 때 세션 ID를 재생성하도록주의를 기울여야합니다 .


질문 : 이것을 호출하면 매분마다 jsut라고 말하면 한계가 증가합니까? 예를 들어 10:00에 전화를해서 제한 시간이 11:00이되고 1 분 후 10:01이되면 제한이 11:01이됩니까?
oneofakind

@oneofakind : 정확히 무엇을 부르면?
Jon

1
이것들 : ini_set ( 'session.gc_maxlifetime', 3600); session_set_cookie_params (3600);
oneofakind

@oneofakind : 예, 그러나 전화를 걸 session_start()거나 (그렇지 않으면 전혀 영향을 미치지 않는 경우) 항상 두 시간 전에 전화를 한 경우에만 session_start(그렇지 않으면 gc_maxlifetime현재 열려있는 모든 세션에 영향을 줄 가능성이 있지만 session_set_cookie_params시작하는 새 세션에만 영향을 줄 수 있음) 현재 요청).
Jon

@Jon session_start ()를 다시 호출하면 $ _SESSION의 모든 것이 재설정됩니까? "모든 세션에 영향을 줄 수있는 잠재력을 가지고있다"는 말은 어떻습니까? 답장을 보내 주셔서 감사합니다.
oneofakind

33

PHP의 기본 세션 처리를 사용하는 경우 모든 플랫폼에서 세션 지속 시간을 안정적으로 변경하는 유일한 방법은 php.ini 를 변경하는 것 입니다. 일부 플랫폼에서는 가비지 수집이 php.ini 에서 직접 읽는 특정 시간마다 실행되는 스크립트 ( cron 스크립트)를 통해 구현 되므로 런타임에이를 변경하려는 시도 (예 : via )는 신뢰할 수없고 가능성이 높기 때문입니다. 작동하지 않습니다.ini_set()

예를 들어, 데비안 리눅스 시스템에서, PHP의 내부 가비지 수집은 설정 session.gc_probability=0에서 기본적 으로 설정 하여 비활성화되며 , 대신 XX : 09와 XX : 39에서 실행되는 /etc/cron.d/php를 통해 수행됩니다 (즉, 30 분마다). 이 크론 작업은 구성에 지정된 session.gc_maxlifetime 보다 오래된 세션을 찾고 발견 된 경우 삭제됩니다. 결과적으로 이러한 시스템 ini_set('session.gc_maxlifetime', ...)에서는 무시됩니다. 또한이 질문에서 이유를 설명합니다. PHP 세션 시간이 너무 빨리 초과 되어 OP가 한 호스트에 문제가 있었지만 다른 호스트로 전환 할 때 문제가 중단되었습니다.

따라서 php.ini에 액세스 할 수 없기 때문에 이식 가능하게하려면 기본 세션 처리를 사용하는 것이 옵션이 아닙니다. 쿠키 수명을 연장하는 것은 호스트에게는 충분했지만 호스트를 전환하더라도 안정적으로 작동하는 솔루션을 원한다면 다른 대안을 사용해야합니다.

사용 가능한 대체 방법은 다음과 같습니다.

  1. PHP : Custom Session Handlers (PHP manual)에 지정된대로 다른 디렉토리 또는 데이터베이스에 세션을 저장하도록 PHP에서 다른 세션 (저장) 처리기 를 설정하십시오. cron 작업이 도달하지 않고 PHP 만 내부 가비지 콜렉션이 발생합니다. 이 옵션은 session.gc_maxlifetimeini_set() 을 설정하는 데 사용할 수 있지만 콜백 에서 maxlifetime 매개 변수를 무시하고 최대 수명을 결정 하는 것을 선호합니다 .gc()

  2. PHP 내부 세션 처리를 완전히 잊고 자신의 세션 관리를 구현하십시오. 이 방법에는 두 가지 주요 단점이 있습니다. 자체 글로벌 세션 변수가 필요하므로 $_SESSION수퍼 글로벌의 이점을 잃어 버리고 더 많은 코드가 필요하므로 버그와 보안 결함에 대한 기회가 더 많습니다. 가장 중요한 것은 세션 ID는 세션 ID 예측 가능성 (세션 하이재킹으로 이어질 수 있음)을 피하기 위해 암호로 안전한 임의 또는 의사 난수로 생성되어야하며 PHP로 이식하기가 쉽지 않습니다. 주요 이점은 모든 플랫폼에서 일관되게 작동하며 코드를 완전히 제어 할 수 있다는 것입니다. 그것은 phpBB 포럼 소프트웨어 (적어도 버전 1; 최신 버전에 대해서는 잘 모르겠습니다)와 같은 접근 방식 입니다.

설명서session_set_save_handler() 에 (1)의 예가 있습니다 . 예제는 길지만 여기서는 세션 지속 시간을 연장하는 데 필요한 관련 수정 사항과 함께이를 재현 할 것입니다. session_set_cookie_params()쿠키 수명을 늘리기 위한 포함도 주목하십시오 .

<?php
class FileSessionHandler
{

    private $savePath;
    private $lifetime;

    function open($savePath, $sessionName)
    {
        $this->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

접근법 (2)은 더 복잡하다. 기본적으로 모든 세션 기능을 자체적으로 다시 구현해야합니다. 여기에 대해서는 자세히 설명하지 않겠습니다.


누구든지 확인할 수 있습니까?
Oli

@Oli : 커서를 읽은 후 올바르게 보입니다. stackoverflow.com/questions/520237/… 을보고 싶을 수도 있지만 php.ini실제 옵션에 액세스 할 수없는 경우 에는 엄격하게 제한됩니다.
Jon

또한 우분투 14 /usr/lib/php5/maxlifetime에서는 24 분 미만의 값을 계산하지 않는 것처럼 보입니다 . 따라서 세션 시간 초과를 이보다 낮게 설정할 수 없습니다.
Henry

"PHP 내부 세션 처리를 완전히 잊어 버리고 자체 세션 관리를 구현하십시오." 좋은 신, 위험한 조언이다. 보안 악몽이 필연적으로 발생합니다.
Kzqai

@Kzqai 나는 또한 "더 많은 코드가 필요하므로 버그와 보안 결함에 대한 더 많은 기회가있다"고 언급했다. 그것은 조언이 아니며 대안을 열거하고 있지만 개선 제안이 있으면하십시오.
페드로 지 메노

3

Plesk가 cron에서 실행하는 자체 가비지 수집 스크립트를 가지고 있으므로 PHP 스크립트에서 session.gc_maxlifetime을 설정하면 위의 문제가있는 Plesk를 사용하는 사람에게 의견을 추가하는 것이 좋습니다.

이 문제를 피하기 위해 cron 작업을 매시간마다 매일 이동하는 아래 링크에 게시 된 솔루션을 사용하면 위의 최상위 답변이 작동합니다.

mv /etc/cron.hourly/plesk-php-cleanuper /etc/cron.daily/

https://websavers.ca/plesk-php-sessions-timing-earlier-expected


3

$_SESSION['login_time'] = time();이전 인증 페이지에 넣 습니다. 세션 시간 제한을 확인하려는 다른 모든 페이지에서 아래로 스니핑하십시오.

if(time() - $_SESSION['login_time'] >= 1800){
    session_destroy(); // destroy session.
    header("Location: logout.php");
    die(); // See https://thedailywtf.com/articles/WellIntentioned-Destruction
    //redirect if the page is inactive for 30 minutes
}
else {        
   $_SESSION['login_time'] = time();
   // update 'login_time' to the last time a page containing this code was accessed.
}

편집 : 다른 게시물에서 이미 조정을 사용했거나 가비지 콜렉션을 사용하지 않고 세션 지속 시간을 수동으로 확인하려는 경우에만 작동합니다. die()일부 스크립트 / 로봇은이를 무시할 수 있으므로 리디렉션 후 추가 하는 것을 잊지 마십시오 . 또한 session_destroy()악의적 인 클라이언트 나 로봇의 경우 리디렉션을 사용하는 대신 세션을 직접 삭제 하는 것이 더 나은 옵션 일 수 있습니다.


2

공유 호스팅 서버에 대한 공지 또는 도메인에 추가 된 경우 =

설정이 작동하려면 php_value session.save_path "folderA / sessionsA"를 사용하여 추가 된 도메인에 대해 다른 저장 세션 디렉토리가 있어야합니다.

따라서 public_html이 아닌 루트 서버에 폴더를 작성하고 외부에서 공개적으로 액세스하지 않도록하십시오. 내 cpanel / server의 경우 폴더 권한 0700이 정상적으로 작동했습니다. 시도해보십시오 ...

  • PHP 코드 =

     #Session timeout, 2628000 sec = 1 month, 604800 = 1 week, 57600 = 16 hours, 86400 = 1 day
     ini_set('session.save_path', '/home/server/.folderA_sessionsA');
     ini_set('session.gc_maxlifetime', 57600); 
     ini_set('session.cookie_lifetime', 57600);
     ini_set('session.cache_expire', 57600);
     ini_set('session.name', 'MyDomainA');

session_start () 이전에;

또는

  • .htaccess =

     php_value session.save_path /home/server/.folderA_sessionsA
     php_value session.gc_maxlifetime 57600
     php_value session.cookie_lifetime 57600
     php_value session.cache_expire 57600
     php_value session.name MyDomainA

많은 연구와 테스트를 거친 후에는 공유 cpanel / php7 서버에서 제대로 작동했습니다. 많은 감사 : NoiS


1

아니요. php.ini에 액세스 할 수없는 경우 변경 사항이 영향을 줄 것이라고 보장 할 수 없습니다.

그래도 세션 시간을 연장해야한다고 의심합니다.
현재 시간이 꽤 합리적이며 시간을 연장 할 이유가 없습니다.


안녕 콜, 나는 당신에게 연락하는 방법을 찾기 위해이 곳곳을 찾고 있습니다. 마지막 게시물 (일요일)에 대해 몇 가지 제안을하는 것을 보았습니다. 다른 프로젝트로 바빠서 이제 사라졌습니다. 나는 당신의 제안을 정말로 시도하고 싶습니다. 어쨌든 당신이 쓴 것을 찾을 수 있습니까?
늙은 개

내가 볼 수있는 한, 그것은 폐쇄되었을뿐만 아니라 삭제되었다. 이 사람들은 영광이 없습니다. 예, 귀하의 문제에는 내가 이야기 한 일반적인 해결책이 있습니다. 이메일로 알려 드리겠습니다. 즉, 이전 / 다음 값을 얻기 위해 2 개의 추가 쿼리를 실행하는 것이 었습니다. SELECT id FROM gallery WHERE SortOrder > $currentsortorder LIMIT 1
당신의 상식

0

을 사용하여 PHP 코드에서 php.ini의 값을 무시할 수 있습니다 ini_set().


4
-1 : session.gc_maxlifetime세션 수명을 제어하는 ​​설정이 아닙니다. 그것은 당신이 설정 한 경우 그와 같은 작업에 몽둥이로 수 session.gc_divisor1있지만, 그건 그냥 끔찍한입니다.
Jon

1
@Jon 나는 그 반대의 제안에 대한 많은 답변을 보았습니다. 왜 그렇습니까? stackoverflow.com/questions/514155/… stackoverflow.com/questions/9904105/…
giannis christofakis

2
@yannishristofakis : gc_maxlifetime세션 데이터가 가비지 수집에 적합한 간격을 설정합니다 . 시간이 지난 후에 GC가 발생하면 세션 데이터가 삭제됩니다 (기본 설정을 사용하면 세션 만료와 동일). 그러나 GC는 세션이 시작될 때마다 확률 적으로 트리거되므로 세션이 실제로 만료된다는 보장이 없습니다. 프로브 대 시간의 곡선을 그릴 수는 있지만 벽돌 벽처럼 보이지는 않습니다. 그것은 빙산의 일각 일뿐입니다. 참조 stackoverflow.com/questions/520237/...
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.