• 「セッション切れ時
    の対応」について、セッションを削除してみたり色々と試...
  • guest 
    「セッション切れ時の対応」について、セッションを削除してみたり色々と試してみましたが、分からないので、教えていただければと思います。

    ・「auth.php」について、「ログインしている」が「セッション切れ」の場合についての質問です。
    この場合、もしログインページのアドレス「~/login.php」を無理やり入力した場合、(「login.php」に飛ぶように設定しているので)無限ループになるのではないかと考えました。

    ここに「if(basename($_SERVER['PHP_SELF']) !== 'login.php')」が入っていないのには、何か理由がありますか?

    自分なりに考えてみた答えは、「session_destroy();」をすれば、login.phpにいても、無限ループにならない何らかの理由がある…?
    又は、そもそも「ログインしている」が「セッション切れ」の場合は、login.phpにいないからif文が入っていない…?(ただ、ログインページのアドレス「~/login.php」を無理やり入力は、できる。)

    などと考えましたが、調べてみましたが、要領を得た回答がありませんでした。

    少し混乱してよく分からなかくなってしまったため、教えていただければと思います。
    ご回答お待ちしております。
    回答 0

    ウェブカツコーチ 
    >「auth.php」について、「ログインしている」が「セッション切れ」の場合についての質問です。
    >この場合、もしログインページのアドレス「~/login.php」を無理やり入力した場合、
    >(「login.php」に飛ぶように設定しているので)無限ループになるのではないかと考えました。

    無限ループにならないですね。

    まず前提として、ログイン自体をどのように管理しているか理解する必要があります。

    login.phpのログインに成功した後の処理の、66行目付近
    $_SESSION['login_date'] = time();
    と、77行目付近、
    $_SESSION['login_limit'] = $sesLimit * 24 * 30;
    79行目付近、
    $_SESSION['user_id'] = $result['id'];
    とあるように、
    $_SESSIONの値に、この3つのパラメータを渡しています。
    その上で、auth.phpで
    ・7行目付近の$_SESSION['login_date']があるかどうか
    ・11行目付近の($_SESSION['login_date'] + $_SESSION['login_limit']) < time()、
     すなわちログインしてから指定の時間($_SESSION['login_limit'])より経過していないか
    を2条件をチェックして、ユーザーがログインしているかどうかを判断しています。

    このことを押さえた上で、
    セッションが切れたときに再度login.phpをURLで入力してアクセスした場合に、
    処理がどうなるか読み解いて行けば、なぜリダイレクトループしないか、今のコードで問題なく動くか理解できます。
    実際にみていきましょう。

    まず、ログインした状態で、セッションが切れる有効期限が切れると、
    auth.phpの15行目付近の
    関数session_destroy()で
    $_SESSIONの中身が破棄されます。
    $_SESSIONの中身がなくなるということは、先程のログインしている2つの条件を満たさないことになるので、
    すなわち、この関数session_destroy()でログアウトしたことになります。

    その後に、URLに再度login.phpを入力した場合、
    $_SESSIONは破棄されているので、
    auth.phpの7行目付近の
    if(!empty($_SESSION['login_date'])){
    でfalseになるため、
    同34行目付近の
    debug('未ログインユーザーです。');
    の分岐の処理へ進みます。
    そして、35行目付近のif文でlogin.phpで無限ループしないようにしているため、
    問題なくlogin.phpは表示されます。

    整理すると、要は、一度有効期限切れすると、関数session_destroy()でログアウトした状態になり、
    つまり、変数$_SESSIONが破棄されます。
    そのため、次にlogin.phpにアクセスした場合は、!empty($_SESSION['login_date'])がfalseとなり、
    その着目されている箇所の処理は行われない
    ということです。

    もしセッションの理解を確認したい場合は、
    下記の記事がよくまとまっていますので参考にしてください。
    https://qiita.com/7968/items/ce03feb17c8eaa6e4672#%E7%AC%AC2%E7%AB%A0-%E3%82%BB%E3%83%83%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6

    guest 
    順を追っての丁寧なご回答、ありがとうございます。
    セッションの記事も参考にさせていただき、より理解が深まりました。

    そこで、もう一つ疑問が沸き上がりまして…。
    お手数をおかけしますが、再度確認と質問をさせてください。

    「①セッションが切れる瞬間はいつか」
    「②header('Location:login.php');は必要ないのではないか」
    という疑問です。


    ①ご回答頂いていた分を読み解くと、

    「セッションが切れる瞬間」…ログインページにいれば、こちらの時間($_SESSION['login_date'] + $_SESSION['login_limit'] < time())が来れば、自動的にセッションが削除される(リロード等押していなくても)という認識を持ちました。

    こちらの認識で間違いなかったでしょうか?


    ②ただ例えば、もしセッションが切れる瞬間が、ログインページに入ろうとした際(URL入力&エンター押した瞬間)であれば、以下の2つの処理が、順に一度で行われる(以下のような処理)ため、
    ・session_destroy();後の「header('Location:login.php');」の処理はいらないのでは・・・?
    とも考えました。

    ※「ログインしている」が「セッション切れ」てしまった際


    1. session_destroy();のみが行われる。

    2. $_SESSIONの中身が無くなるので、header('Location:login.php');までは続かず、もう一度auth.phpの初めに戻って処理が行われる。

    3. $_SESSION['login_date']が破棄されてないので、35行目の
    if(basename($_SERVER['PHP_SELF']) !== 'login.php'){
    header('Location:login.php');
    の処理が走る。


    試しに、以下の挙動の下にデバックを付け、
    ログイン⇒セッション切れを起こさせる⇒プロフィール画面にログインしてみたところ、「未ログイン時」の挙動をしているようでした。
    ・「ログインしているがセッション切れ」(19行目)
    ・「未ログイン時」(38行目)


    もしかすると見当違いのことを言っているかもしれず、
    再度お手数をおかけしますが、ご確認いただきご返答いただけますと幸いです。
    どうぞよろしくお願いいたします。

    ウェブカツコーチ 
    >①ご回答頂いていた分を読み解くと、
    >「セッションが切れる瞬間」…ログインページにいれば、こちらの時間($_SESSION['login_date'] + $_SESSION['login_limit'] < time())が来れば、自動的にセッションが削除される(リロード等押していなくても)という認識を持ちました。
    >こちらの認識で間違いなかったでしょうか?

    「自動的にセッションが削除される」というのをどのような理解をされているかこちらで確認するため、
    この部分の処理の流れを再度説明させてください。
    ログインページだけでなく、他のページでも
    require_once('auth.php')
    が記載されていれば、そのページにアクセスするたびに、auth.phpが実行されます。
    その実行されるごとに
    ($_SESSION['login_date'] + $_SESSION['login_limit'] < time())
    の条件が正なら、
    関数session_destroy()でセッションを削除しています。

    セッションである変数$_SESSIONは自動的に削除されるものではなく、
    関数session_destroy()とプログラムできちんと指示をして、セッションを削除する必要があります。
    時間が経てば自動で変数が削除されるというものではありません。

    >1. session_destroy();のみが行われる。
    >2. $_SESSIONの中身が無くなるので、header('Location:login.php');までは続かず、もう一度auth.phpの初めに戻って処理が行われる。
    >3. $_SESSION['login_date']が破棄されてないので、35行目の
    >if(basename($_SERVER['PHP_SELF']) !== 'login.php'){
    >header('Location:login.php');
    >の処理が走る。

    >2. $_SESSIONの中身が無くなるので、header('Location:login.php');までは続かず、もう一度auth.phpの初めに戻って処理が行われる。
    ここが理解が間違っているかもしれないので、確認させてください。
    session_destroy()が行われた後、$_SESSIONがなくなったからといって、
    そこでプログラムの処理は途中で終わりません。
    そのまま、header('Location:login.php');で、login.phpに遷移します。

    その後、login.phpに遷移した後、再度auth.phpが実行されます。
    このとき、リダイレクト前に$_SESSIONは削除されているので、
    7行目付近の
    if( !empty($_SESSION['login_date']) )
    はfalseとなり、
    35行目の
    if(basename($_SERVER['PHP_SELF']) !== 'login.php'){
    header('Location:login.php');
    の処理が行われます。

    17行目付近の
    header("Location:login.php");
    があるのは、
    login.php以外の画面にアクセスしてセッションが切れていた場合にlogin.phpへリダイレクトするためです。
    具体的には、ログインしてしばらく経過した後、login.php以外の画面にアクセスした時、
    auth.phpが実行され、ログイン後一定時間が経っていると、
    ($_SESSION['login_date'] + $_SESSION['login_limit'] < time())
    が正なので、関数session_destroy()でセッションが削除されます。
    その後、login.phpに遷移します。
    実際にウェブサービスを触っている時に、ログイン後しばらくしてからそのサービスの操作をするとログイン画面に遷移することがあると思います。
    それと同じ処理です。

    一方でlogin.phpにアクセスした時にセッションが削除された場合、
    header("Location:login.php");
    があるため再度login.phpに遷移するわけですが、
    この2回目のlogin.phpでは、$_SESSIONが削除されているため
    if( !empty($_SESSION['login_date']) )はfalseとなります。
    したがって、その35行目以降の処理が行われるため、ループは起こりません。

    login.phpからlogin.phpへと移動して無駄な処理のように見えますが、
    上記の通り、他のページにアクセスしてauth.phpを実行した場合の処理も兼ねているため、
    プログラムとしては合理的な書き方となっています。

    念のため、下記の点を理解されているか確認してみてください。
    ・auth.phpの役割は、ログインしているか・ログインして時間が経ちすぎていないかチェックをすることです。
     login.php(ログイン画面)以外でも、require_once('auth.php')と書いているページのファイルでも実行されます。
    ・$_SESSION変数は、他の変数と異なり、
     関数session_start()を利用すれば、他のページに移動した時にその移動前の$_SESSIONの中身を保持できます。
    ・$_SESSION変数の破棄は、自動で行われず、関数session_destroy()を実行する必要があります。

    guest 
    すごくご丁寧に説明いただき、ありがとうございます。
    ようやく引っ掛かりが取れました!

    login.php⇒header("Location:login.php")に行っただけで=即無限ループしてしまうと勘違いをしていたため、ずっと悩んでおりました。

    頂いていた、以下のご回答部分のおかげで、理解することができました。

    >一方でlogin.phpにアクセスした時にセッションが削除された場合、
    header("Location:login.php");
    があるため再度login.phpに遷移するわけですが、
    この2回目のlogin.phpでは、$_SESSIONが削除されているため
    if( !empty($_SESSION['login_date']) )はfalseとなります。
    したがって、その35行目以降の処理が行われるため、ループは起こりません。

    頂いていた確認部分も、再度確認させていただき、理解が深まりました。
    ご丁寧にありがとうございました!