質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

2回答

4803閲覧

phpにおけるセッション破棄の使い方について

hatsuzo

総合スコア56

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2019/06/20 06:55

編集2019/06/20 07:28

度々お世話になっております。
phpによる基礎的なセッションタイムアウトの方法について
で質問させて頂いた者です。

一定時間が経過後にタイムアウトを行わせる画面遷移を考えておりますが、アドバイスを頂いたおかげで、基本的な流れを作るところまで辿り着きました。考え方はこうです。
<画面A>
セッションが無い時は作成し、開いた時間をセッション変数(t)にSAVE
セッションがある場合は、開いた時間をセッション変数(t)と比較して、一定時間経過後に画面Bに遷移させる。
<画面B>
セッションの削除
エラーメッセージを表示してボタン押下時に画面を閉じる

基本的にはこの画面でほぼ動作することを確認しましたので、最終的には、各画面に<画面A>と同じチェック処理を入れることを考えています。

確認の動作としては、

  • <画面A>で一定時間後に、画面をリロードすると、<画面B>に遷移
  • <画面B>でスクリプトを閉じる操作をした時、フォームは閉じるが、空白の画面が残る。
  • 再度、<画面A>を呼び出した時も、同じ動作になる

ことを確認しました。

ただ、この時、<画面B>の状態でブラウザの戻るボタンを押すと、<画面A>に戻ってしまうため、それを防止するため、

javascript

1window.onunload = function(){}; 2history.forward();

と入れたところ、<画面A>に戻らなくなったので、無事解決となりました。
ところが、<画面A>のURLを呼び出したところ、<画面A>の処理の中で、セッションが残っている状態、つまり、(if(isset($_SESSION['LOGIN_INFO'])))と判定され、自動的に<画面B>に遷移する動きになってしまいました。

再度呼び出しても同じなのですが、<画面B>で戻るボタンを一度押した状態で、<画面A>を呼び出したところ、呼び出せることが判ったのですが、解決策が見つからなく困っております。

おそらくセッションの解放のしかたに問題があるのではないかと思うのですが、識者のアドバイスを頂ければ幸いです。

PC側の実行環境は、Windows10で、ChromeとFirefoxでこの状況になります。IE11だとフォームを完全にクローズするため、この現象は出ません。

php

1<画面A> 2<?php 3 if( !isset( $_SESSION ) ) { 4 session_start(); 5 } 6 // セッションが存在していない(タイムアウトもしくはログアウトされている) 7 if(!isset($_SESSION['LOGIN_INFO'])) { 8 $_SESSION['LOGIN_INFO'] = true; 9 $_SESSION['LAST_TIME'] = date("Y-m-d H:i:s"); 10 // セッションが存在している場合はセッションのライフタイムを更新 11 } else { 12 $_SESSION['LOGIN_INFO'] = true; 13 $last_tm = $_SESSION['LAST_TIME']; 14 $_SESSION['LAST_TIME'] = date("Y-m-d H:i:s"); 15 print "last:{$last_tm}<br />"; 16 print "now:{$_SESSION['LAST_TIME']}<br />"; 17 // 時刻差(秒数) 18 $diff_min = (strtotime($_SESSION['LAST_TIME']) - strtotime($last_tm)); 19 if ($diff_min > 5){ 20 echo "<script> window.location.replace('ss_timeout.php'); history.pushState(null, null, null); </script>"; 21 } 22 } 23 echo "<br /><a href='sess02.php'>サンプル画面2へ</a>"; 24?>

html

1<画面B> 2<html> 3<head> 4<script language="JavaScript"> 5<!-- 6window.onunload = function(){}; 7history.forward(); 8//--> 9</script> 10</head> 11<body> 12<?php 13// セッションの切断 14if( isset( $_SESSION ) ) { 15 $_SESSION = array(); 16 if (isset($_COOKIE["PHPSESSID"])) { 17 setcookie("PHPSESSID", '', time() - 1800, '/'); 18 } 19 session_destroy(); 20} 21?> 22<div> 23 <p>長時間使用されていないため、タイムアウトが発生しました。</p> 24 <p>「閉じる」ボタンをクリックして終了して下さい。</p> 25 <p><div align="center"><a href="javascript:window.open('about:blank','_self').close();">閉じる</a></div></p> 26</div> 27</body> 28</html>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

ちょっと質問の主旨が理解できていませんが、session の取扱を理解していないように思います。

ざっと気になった点を羅列します。
・$_SESSION を使用するのであれば、それより前に session_start() が必要です。
・time-out の処理の中で、$_SESSION['LOGIN_INFO'] の中身を変更していないので、true が残り続けています。

いわゆるログアウトの処理になると思いますので、ログアウト機能の目的と実現方法 を参照の上、実装すると良いです。

投稿2019/06/20 09:45

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/06/20 09:48

画面B で session 破棄をしようとしているんですかね? であれば、1番目の項目だけ見ればよいかと。 個人的には、画面 A の time-out 処理の中でログアウトさせたいですけど。
hatsuzo

2019/06/21 05:39

コメントありがとうございます。 if( !isset( $_SESSION ) ) { session_start(); } の部分は実は私もよく理解せず、ネット上のサンプルを見て使っていましたが、確かにセッションが無い時はエラーになりますので変ですね。 $_SESSION['LOGIN_INFO'] をその後、特に使う必要も無ければ、単純に$_SESSION['LAST_TIME']の有無だけでセッションの継続の判断をすればよいということですね? 確かにそこでさせても問題ないですね。 何れにしても、戻るキーでの所作を止める必要はあるかと思いますので、そこでちょっと行き詰っています。IEの場合は問題ないのですが、Chromeで戻るキーを止めるのはなかなかうまくいきませんが、セッションの考え方とは別問題、ということのようですね。 戻るキーを押した時は、当然画面のリロードはされない訳なので厄介ですね。
guest

0

<画面A>

セッションが無い時は作成し、開いた時間をセッション変数(t)にSAVE
セッションがある場合は、開いた時間をセッション変数(t)と比較して、一定時間経過後に画面Bに遷移させる。

そもそもプログラム側でセッション時間比較せずとも、セッション有効期間の設定でセッション値が取れなくなるので不要です。
画面を最初に開いた時からの経過時間を制限したい場合は、クッキーの有効期間で制御します。

session.cookie_lifetime
ブラウザにセッションIDのCookieを発行する際のCookieの有効期限。
ブラウザはこの期限を過ぎるとCookieを破棄するので、結果としてセッションが途切れることになる。
デフォルトは0で"ブラウザを閉じるまで"という意味。

session.gc_maxlifetime
サーバに保存されているセッションファイルを保護する有効期限。
セッションデータそのものの有効期限ではないし、そのような設定項目はない。
リロードされないまま有効期限を過ぎたら、その後セッションファイルが削除される可能性がある。

session.gc_divisor
session.gc_maxlifetimeを過ぎると必ずセッションファイルが削除されるわけではなく、PHPにリクエストがあったときに(session.gc_probability / session.gc_divisor)の確率でGCが起動して実際に削除される。
セッションファイルそのものには有効期限は書かれていないため、session.gc_maxlifetimeを過ぎてもGC起動前であればセッションデータにアクセス可能。
デフォルトはsession.gc_probability=1、session.gc_divisor=100で、1%の確率でGCが起動する。

投稿2019/06/20 07:54

編集2019/06/20 09:48
hide0128

総合スコア245

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hatsuzo

2019/06/20 08:56

コメントありがとうございます。 私も仰る通り、最初はそうした考え方でよいと思っていました。 しかし、有効時間の設定をしても思うように動作してくれなかったこと、 それから、要件として、同じ画面で一定期間以上過ぎたら、使えないようにしたかった訳でして、 各画面で前画面との比較をしながら、session_startを実行する前に有効期間は決められないと思ったからです。そこで行き詰っていたところ、毎回、前画面との時間比較をしたらうまく判定できたので、そのような方法を取った次第です。 画面を変える度に別のセッションにしなくても、有効期限を動的に設定することができるのでしょうか?
hide0128

2019/06/20 09:28

>有効時間の設定をしても思うように動作してくれなかったこと 安易に回避措置を取るより まず、この原因を究明しましょう。 一度、セッションとクッキーの有効期間を確認してください。 そしてセッションについて勉強してみてください。
退会済みユーザー

退会済みユーザー

2019/06/20 10:06

一つ前の質問に回答しましたが、設定によるセッションの有効時間のコントロールは、悪手とまでは言わないものの、良い手では無いと思っています。 session 自体に時間を記述する方法はよく見かける手なので問題はないかと。
hide0128

2019/06/20 10:26

各画面でやりたい事とは別に設定は重要です。 session.gc_maxlifetimeが大きいと膨大なデータが残り負荷になります。 クッキーの有効期間に関してもセキュリティ的に問題が出るでしょう。 おそらくやりたい事はクッキーの有効時間の設定が抜けているからではないでしょうか。
退会済みユーザー

退会済みユーザー

2019/06/20 12:54

session.gc_maxlifetime が session 機能を安定して使うために必須な設定であり、session.cookie_lifetime が 0 のままでは、私の提案する方法もあまり効果はないというのは事実ですが、やはり「コントロール」するという観点からはずれがあると思います。 あくまで「有効期限をコントロール」する観点では、「session に突っ込んだ時刻」を比較するのが適切だと考えます。
hatsuzo

2019/06/21 03:56

hide0218さん、te2jiさん コメントありがとうございます。 セッションの使い方と意味をよく理解していないので、うまく表現できないのですが、 セッション単位での有効期限を設定して、その期間オーバーをチェックしようとすると、 画面間の遷移が一つのセッションということになる?と理解していて、 画面の処理全体を一つのセッションとして捉えておけば、その中の一つ一つの画面に対する到達時間を比較し、セッションの終了は、正常にログアウトした時とタイムアウトした時にすればよいかなと考えて、te2jiさんのご意見を参考にさせて頂いたわけです。
hide0128

2019/06/21 08:44

te2jiさん、hatsuzoさん やりたい事によってコントロールに使用するものは変わってくると思います。 ログインなどの時間制限はセッションクッキーの期限で←私の知る限り、多くのフレームワークではそうしています。 それ以外、個別の機能であればセッションに突っ込んでプログラムで制御しても良いですが、お勧め出来ません。 単純に個別の期限付きクッキーを発行すれば解決です。
退会済みユーザー

退会済みユーザー

2019/06/21 10:06

繰り返しになりますが、cookie はユーザの時計に依存しますし、ましてや「書き換えることが可能」なので、要件で「有効期限をコントロール」する必要がある場合は、cookie の有効期限に依存させるのは不適切です。 *GCでは正確な有効期限が設定できません。
退会済みユーザー

退会済みユーザー

2019/06/21 10:16

> *GCでは正確な有効期限が設定できません。 試してないですが、time-out 時に session_gc() するのであれば、正確に制御できるかもしれないですね。。。
退会済みユーザー

退会済みユーザー

2019/06/21 10:17

でも、元になる時間が必要か^^;失礼。やっぱり制御できないと思います。
hide0128

2019/06/21 10:57

おっしゃる通りクッキーはクライアントに依存するので、厳密に時間をコントロールするのでしたらセッション管理が良いですね。
hatsuzo

2019/06/24 10:17

hide0128さん コメントありがとうございます。 ちょっと私には理解できないレベルになってしまいました。 セッションはログインからログアウトに至るまでの間の時間を意味するものという理解だったので、その有効期限は全体の寿命を表すものであって、セッション内部での一つ一つの画面遷移の経過時間を取るのになぜセッションの有効時間を使うのか理解に苦しみます。 もう少し理解が深まったらもう一度考え直してみようと思いますが、ひとまず、セッション変数を使ってその値をCookieに保存して、という当初の方法で実装しようと思います。 有難うございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問