30分後にPHPセッションを期限切れにするにはどうすればよいですか?


1047

セッションを30分間存続させてから破棄する必要があります。


35
セッション時間を設定するには少なくとも2つの設定が重要であり、おそらく3つであることに注意してください。確かに重要な2つは、session.gc_maxlifetimeとsession.cookie_lifetimeです(0は長い数値と同じではありません)。完全に、100%確実に長い時間を許可するには、セッションファイルがデフォルトで格納される/ tmpディレクトリでOSが制御するクリーンアップ時間が異なるため、session.save_pathを設定する必要がある場合もあります。
Kzqai

1
セッションを期限切れにする理由がわかりません。ユーザーがログアウトせずにコンピューターを離れることを心配し、権限のないユーザーがコンピューターを乗っ取っても、サイトでのセッションの期限切れは、ハイジャック犯がディスク上の被害者のファイルにアクセスすることを妨げません。
Gqqnbig 2018年

ここで何を求めているのかは不明です。ハード非アクティブタイムアウトを実装することを意味しますか(現在、PHPは幸いにも、session.gc_maxlifetimeを超えて触れられていないセッションを使用できるようにします)、それとも、セッションを30分に制限しますか?非活動?率直に言って、ここで受け入れられた答えはどちらの問題にもかなり悪いアドバイスです-どちらの場合も、ロジックはカスタムセッションハンドラーで実装する必要があります。
symcbean '19

回答:


1663

独自のセッションタイムアウトを実装する必要があります。他の人が言及した両方のオプション(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以降では、atimeではなくmtime(変更日)を使用しています。したがって、atimeトラッキングが利用できないファイルシステムでは問題は発生しません。

そのため、セッションデータが最近更新されなかったために、セッション自体がまだ有効であると見なされている間に、セッションデータファイルが削除される場合もあります。

そして2番目:

session.cookie_lifetime
session.cookie_lifetimeは、ブラウザーに送信されるCookieの存続時間を秒単位で指定します。[…]

はい、そうです。これはCookieの有効期間にのみ影響し、セッション自体はまだ有効である可能性があります。ただし、セッションを無効にするのはクライアントではなくサーバーのタスクです。だからこれは何の助けにもなりません。実際、session.cookie_lifetimeをに設定する0と、セッションのCookieは、ブラウザが閉じられるまでのみ有効な実際のセッション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

リクエストごとにセッションデータを更新すると、セッションファイルの変更日も変更されるため、ガベージコレクタによってセッションが途中で削除されることはありません。

追加のタイムスタンプを使用して定期的にセッション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)と等しくなければなりません。
  • 開始から30分後ではなく、アクティビティの 30分後にセッションを期限切れにしたい場合は、セッションCookieをアクティブにしておくために、有効期限切れのを使用する必要もあります。setcookietime()+60*30

3
「非アクティブ時間」を確認したい場合、これをどのように変更できますか?つまり、ユーザーはログインし、サイトを引き続き使用している限り、ログアウトしません。ただし、30分間アクティブでない場合、ログアウトしますか?
メトロポリス

14
@Metropolis:ユーザーの最後のアクティビティの時間を保存するような$_SESSION['LAST_ACTIVITY']ものを使用$_SESSION['CREATED']しますが、すべてのリクエストでその値を更新します。ここで、その時間と現在の時間の差が1800秒より大きい場合、セッションは30分以上使用されていません。
ガンボ

3
@Metropolis:session_unsetと同じ$_SESSION = array()です。
ガンボ

14
@ガンボ-少し混乱しています。コードと組み合わせて使用​​しないでくださいini_set('session.gc-maxlifetime', 1800)。そうでない場合、少なくともini設定が標準の24分である場合、セッションがまだ有効であると想定されているときに、セッション情報が破壊される可能性があります。それとも何か不足していますか?
jeroen

10
@ジェロン:はい、そうすべきです。ただし、セッション保存ハンドラが使用されている場合、session.gc_maxlifetimeはファイルの最終変更日に依存することに注意してくださいfiles。したがって、session.gc_maxlifetimeは、少なくともこのカスタムの有効期限ハンドラの有効期間と同じである必要があります。
ガンボ

135

PHPセッションの簡単な方法は30分で期限切れになります。

注:時間を変更する場合は、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は、1人のプログラマーでプロジェクトが小規模な場合でも良い考えですか?MVCモデルで自分のプロジェクトを作成する必要があるように感じます(または問題を解決してからMVCにしてください)。MVCの経験がないため、「このMVCを作成するにはどうすればよいですか?」ソリューションを必要とする最初の目標/問題からの注意散漫。
MrVimes

@stillstanding別の言及は、Login.phpヘッダーでコンテンツの後に送信されることですが、これは悪いことです。
machineaddict 2018年

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 2009

2
セッションCookieの有効期間にはいくつかの問題があります。最も顕著なのは、それを強制するためにクライアントに依存することです。Cookieの有効期間は、クライアントが無用の/期限切れのCookieをクリーンアップできるようにするためのものであり、セキュリティ関連のものと混同しないでください。
ジャッコ

それgc_maxlifetimegc-maxlifetime。アンダースコアとハイフンの両方をサポートしていますか?
マイクコーザー

24

この投稿は、セッションタイムアウトを制御するいくつかの方法を示しています。http://bytes.com/topic/php/insights/889606-setting-timeout-php-sessions

私見2番目のオプションは良い解決策です:

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

以下のような機能で実は簡単です。データベーステーブル名「sessions」とフィールド「id」および「time」を使用します。

ユーザーがサイトまたはサービスに再度アクセスするたびに、この関数を呼び出して戻り値が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>";
    }
}
?>

タイムスタンプを使用してセッションを期限切れにするために20秒使用しました

30分が必要な場合は、1800(30秒)を追加します...


0

別の方法として、DBをそのまま使用できます。DB関数を使用して、chk_lgnを呼び出します。

ログインチェックをチェックして、それらがログインしているかどうかを確認します。そうすることで、チェックの日付タイムスタンプがユーザーのdb行/列で最後にアクティブに設定されます。

そこで時間チェックもやってます。この機能はすべてのページで使用しているので、今のところこれでうまくいきます。

PS私が見た誰も、純粋なDBソリューションを提案していませんでした。


0

PHPがセッションを処理する方法は、初心者が理解するのにかなり混乱しています。これは、セッションがどのように機能するかの概要を与えることで、彼らを助けるかもしれません:セッションがどのように機能するか (custom-session-handlers)


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.