の対応」について、セッションを削除してみたり色々と試...
>この場合、もしログインページのアドレス「~/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
セッションの記事も参考にさせていただき、より理解が深まりました。
そこで、もう一つ疑問が沸き上がりまして…。
お手数をおかけしますが、再度確認と質問をさせてください。
「①セッションが切れる瞬間はいつか」
「②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()を実行する必要があります。
ようやく引っ掛かりが取れました!
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行目以降の処理が行われるため、ループは起こりません。
頂いていた確認部分も、再度確認させていただき、理解が深まりました。
ご丁寧にありがとうございました!
部活の学習一覧
Lesson 01
「WEBサービスと必要な機能」
Lesson 02
「画面を設計しよう!」
Lesson 03
「テーブルを設計しよう!part1」
Lesson 04
「テーブルを設計しよう!part2」
Lesson 05
「テーブルを設計しよう!part3」
Lesson 06
「DB作成」
Lesson 07
「画面を作ろう!」
Lesson 08
「画面を作ろう!part2」
Lesson 09
「ユーザー登録機能を作ろう!」
Lesson 10
「ユーザー登録機能を作ろう!part2」
コーヒーブレイク
「投資の小話」
Lesson 11
「ログイン機能を作ろう!」
Lesson 12
「ログアウト機能を作ろう!」
Lesson 13
「退会機能を作ろう!」
Lesson 14
「プロフィール編集機能を作ろう!」
コーヒーブレイク
「書いて書いて書きまくれ!」
Lesson 15
「パスワード変更機能を作ろう!」
Lesson 16
「パスワードリマインダー機能を作ろう!」
Lesson 17
「商品登録機能を作ろう!」
Lesson 18
「商品登録機能を作ろう!part2」
Lesson 19
「商品登録機能を作ろう!part3」
Lesson 20
「商品一覧表示機能を作ろう!」
Lesson 21
「商品詳細画面を作ろう!」
Lesson 22
「商品検索機能を作ろう!」
Lesson 23
「連絡掲示板機能を作ろう!」
Lesson 24
「お気に入り機能を作ろう!」
Lesson 25
「マイページ機能を作ろう!」
コーヒーブレイク
「はたらくプログラミング 第5話」
ご意見箱
・「auth.php」について、「ログインしている」が「セッション切れ」の場合についての質問です。
この場合、もしログインページのアドレス「~/login.php」を無理やり入力した場合、(「login.php」に飛ぶように設定しているので)無限ループになるのではないかと考えました。
ここに「if(basename($_SERVER['PHP_SELF']) !== 'login.php')」が入っていないのには、何か理由がありますか?
自分なりに考えてみた答えは、「session_destroy();」をすれば、login.phpにいても、無限ループにならない何らかの理由がある…?
又は、そもそも「ログインしている」が「セッション切れ」の場合は、login.phpにいないからif文が入っていない…?(ただ、ログインページのアドレス「~/login.php」を無理やり入力は、できる。)
などと考えましたが、調べてみましたが、要領を得た回答がありませんでした。
少し混乱してよく分からなかくなってしまったため、教えていただければと思います。
ご回答お待ちしております。