- ベストアンサー
セッションとクッキーの使い分け方法と実装法
- セッションとクッキーは異なる役割を果たすため、使い分けが重要です。セッションはサーバサイドで情報を管理し、クッキーはクライアントサイドに情報を保存します。
- セッションはブラウザを閉じるとデータが消えるため、認証情報のような一時的な情報を扱うのに適しています。認証の終了後はセッションを破棄し、セッションIDをクッキーに保存する方法が一般的です。
- クッキーはブラウザに保存されるため、ログイン状態の維持など、長期間にわたる情報の保存に適しています。ただし、セキュリティ上の注意が必要で、重要な情報はハッシュ化して保存することが推奨されています。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
使い捨てパスワードを発行するとよいでしょう。 ▼Formからログイン >> ID/パスワードの検証 暗号化したパスワードをサーバと比較 (蛇足ながらサーバ側には暗号化したものを保存、生パスワードは扱わない) ▼認証成功 >> ・$_SESSION['user_id']等適宜発行。 ・使い捨てパスワードとして一意の不規則な文字列(32桁あれば十分かと)を生成>> 「自動ログインをオンにする」ならその値でCookie発行。(自動ログインの有効期限をクッキーのexpireとすればよい) ・DBの方の使い捨てパスワード欄も適宜暗号化して更新。 ▼次回接続時 (セッション切断後) cookieに使い捨てパスワードがあれば、暗号化しDBにその値があるか探す。 存在すれば「一意の不規則な文字列」ですから、user_idも判明するので、ログインと同じ処理。 ※自動ログインがオンでない場合は、そのcookieを削除してやります。一方、DBの方は削除してはいけません。(空でヒットすると大変ですので)。DBは自動ログインのオン/オフにかかわらずログインの度に更新してやります。
その他の回答 (5)
- BellBell
- ベストアンサー率54% (327/598)
session.cookie_lifetimeは、名前の通りクッキー有効時間ですね。 デフォルトが0なので、ブラウザを閉じると削除という設定です。 (これを変更すれば、ブラウザが閉じてもセッションは一定期間残せる事になります) サーバー側でセッションの保持期限を設定するのは、session.gc_maxlifetimeです。 /tmp内にセッションIDを元にしたファイル名で、セッションファイルが作られます。 アクセス毎(session_start()毎)に、ファイルの時刻が更新されて、その最終更新時刻が現在時刻とsession.gc_maxlifetimeで設定した時刻より古いと自動的に削除されます。 この場合、いくらクッキーにセッションIDが残っていても、サーバー側で破棄されているのでセッション変数は継続されない事になります。 うろ覚えですが、デフォルトは20分ぐらいだったと思います。 なので、20分以上ユーザーが無操作だとセッションは破棄されて、自動的にログアウトされる事になります。 ※実際にはsession.gc_divisorやsession.gc_probabilityが絡んで、少々ややこしい事になっていますが。 で、session.gc_maxlifetimeを延ばせば無操作でもセッションが保存される期間は延びますが、ここにも少々ややこしい事が。 ローカルでのテストや、専用サーバー(仮想含む)の場合はまったく問題なく動くことが確認できますが、共用サーバーの場合には正しく動かない事があるんです。 同一のサーバーに収容されている別のユーザーによるPHPプログラムによって、自分のシステムのセッションファイルが削除されてしまうからです。 たとえば、2時間セッション変数を残したいとsession.gc_maxlifetimeに7200(秒)を設定しても、デフォルト(20分)設定のPHPプログラムが動いた際に、勝手に削除されて無効になってしまいます。 なので、勝手に削除されないようにsession.save_pathに、自分の管理するフォルダを設定してやらなければなりません。 もっとも、デフォルトの/tmpはそのサーバーの契約者なら(契約者が作ったPHPプログラムを使用すれば)、誰でも簡単に覗ける領域なのでセキュリティ的に情報ダダ漏れなので、どっちみちsession.save_pathの変更は必須ですが。 同様に、自分の作ったプログラム同士でも、20分セッションを保持できればいいプログラムと、2時間保持したいプログラムを同じサーバーで動かしたいなら、それぞれのプログラム同士は別々のディレクトリにセッションを保存する必要があります。 >こういう認証フォームの場合、認証後はセッションの内容はブラウザを閉じられるまでずっと保持しておくように実装するものなのでしょうか? >それとも、認証が終わったら、基本的には削除するものなのでしょうか? ログインしたら、ユーザーが自分でログアウトするか、ログイン有効時間(≒session.gc_maxlifetime)まで『ログインしています』という情報(フラグ)は保持し続けるのが普通でしょ? 破棄してしまったら、ちゃんとユーザーID+パスワードで認証をしたユーザーなのか、ログイン後のURLを知っている人が直接URLを打ち込んだ(ブックマーク等を含む)のか、判断する事ができなくなってしまいます。 #1の方が書いているように、誰がログインしているのかとユーザーIDをSESSIONを使って持ち回って、ユーザー毎に別の情報を表示しますね。そのための認証なのでしょうから。 ユーザーIDがSESSIONに格納されていなければ、認証を通っていないというフラグと兼用になります。 ブラウザが閉じられると自動でログアウトするのは当然と私は思っているので、session.cookie_lifetimeはデフォルトの0のままで実装しますね。 この場合は、事実上SESSION変数は破棄されたのと同等です。
お礼
BellBellさん、ご回答ありがとうございます。 >ここにも少々ややこしい事が 確かに共有サーバの場合は何かと色々とややこしいことが多いですよね。 >同様に、自分の作ったプログラム同士でも、20分セッションを保持できればいいプログラムと、2時間保持したいプログラムを同じサーバーで動かしたいなら、それぞれのプログラム同士は別々のディレクトリにセッションを保存する必要があります。 大変参考になりました。 そういう発想は持っておりませんでした。 そのように致します。 >ちゃんとユーザーID+パスワードで認証をしたユーザーなのか、ログイン後のURLを知っている人が直接URLを打ち込んだ(ブックマーク等を含む)のか、判断する事ができなくなってしまいます 確かに。 その事を頭に入れておりませんでした。 正規の認証かどうかは非常に大切ですもんね。
- honoka-cha
- ベストアンサー率54% (40/73)
> セッションだけのものは自分も一応作ってはみたのですが、 そしてそれは目的の機能を果たしていましたか。果たしていたならそれで完了です。 不満点があるなら、それを明確にしたうえで課題解決をはかるのがその後の流れです。 ただ、文章から察するに、抱えているのは機能上の不満ではなく不安なのではないでしょうか。 ネットで検索したらあんなこともやってるこんなこともやってるというのがたくさん見つかったことでしょう。 一方セッションだけを使ったプログラムを振り返ってみると、クッキーもいじっていないし その他こまごまとしたものを何もいじっていないし何か足りないような気がするという 漠然とした不安がありますよね。私も通ってきた道ですのでその気持ちはよくわかります。 しかし漠然とした不安を漠然としたまま、ただ大きいだけの課題を整理せずに走り続けてもゴールに到達しないことも確かです。 ひとつの手として、無用な機能はきっぱり切り捨てることです。 本当に必要なことは何かを絞ってみましょう。 するとゴールは意外とすぐそこにあるものです。 さて、PHPのセッションですが、これはクッキーを利用しています。つまりPHPでセッションを使えば自動的にクッキーも使っています。 セッションもいじり、クッキーも更にいじりというのではいじりすぎなのであまりお勧めしません。 まずセッションだけで機能を満たすことを考え、もしセッションが使えない特別な環境とか セッションだけでは機能不足なことがあるのであれば、 そこでクッキーを使ったり、DBとの複雑な連携を考えたりすればよいのではないでしょうか。 > セッションを使ってログインフォームを作り、認証した後もずっと認証内容を保持していないといけないのかな? しばらくの間、勝手に認証を保持してくれる便利な機能=セッションですので、 何か追加的に超複雑なことをしなければならないかもとお考えなら、そうではないので安心して大丈夫です。 「ずっと」という意味がどういう意味(長さ)なのかにもよりますけどね。
お礼
honoka-chaさん、ご回答ありがとうございます。 確かに不安はあります。 セキュリティとか、普通のhtml文書でなら問題はありませんが、サーバ内に関わってくるので出来るだけ不安を無くしたいと。 ただ、自分はそれ以前の問題で(苦笑)、なぜブラウザを閉じた後でもログイン情報が維持され続けているのかと言うことが分かりませんで。 「クッキーを設定してください」のような文字を昔から見ていますし、「クッキーを削除」をおすとログイン状態は失われます。 自分の思っていたセッションの挙動とは違うので、これはクッキーによる実装によるものだろうと思いまして。 実際ブラウザのクッキーを確認しても、ハッシュ化されて内容は分かりませんが、残っていますので。 という事で、質問の本質は「どうやったらブラウザを閉じたとしても(1週間とか1ヶ月とか)ログイン情報を保持しつづける事ができるのか」です。
- BellBell
- ベストアンサー率54% (327/598)
>簡単に言えばセッションがサーバサイド、クッキーがクライアントサイド、 >セッション内容はブラウザ切れば消える(残すことも出来る)、クッキーはブラウザに残る、 >と言うことは分かっているのですが、実装の仕方が分かりません。 一行目は合っていますが、二行目が大間違いです。 >セッション内容はブラウザ切れば消える セッションはブラウザなどに依存せず、一定時間残ります。 そもそも、PHPプログラムから見ても、HTTPサーバ(Apacheなど)から見ても、ページ読み込み完了後は通信は切断されています。 『ブラウザが閉じられました』という情報を、ブラウザはサーバーに送信しません。 送信されないのですから、ブラウザを閉じたタイミングでセッションを消す方法などあり得ないのです。 PHPの$_SESSIONは、自動的にクッキーに対してセッションIDを保持させます(デフォルト設定の場合)。 そのセッションIDの保持期限が、ブラウザが閉じるまでとなっています。 サーバー側にはセッション変数は残っているのですが、再起動したブラウザにはセッションIDを格納したクッキーが残っていない為、そのセッションにアクセスできない(セッション変数を読みとることができない)のです。 上記『サーバー側にはセッション変数は残っているのですが』というのは、一定期間アクセスのなかったセッション変数は自動的にサーバーが削除すると思ってください。(あくまで概略です) この機能で、セッションが溜まりまくってしまうという事を防いでいます。 とりあえず、ブラウザを閉じなくてもクッキーを削除しさえすれば、セッション変数にアクセスできなくなる事が確認できると思います。 余談ですが、クッキーが使用できないブラウザ(旧型の携帯電話の場合や、ユーザーがクッキーを受け入れないように設定していた場合など)では、『index.php?SESSION_ID=hogehoge』のように、URLパラメータとしてセッションIDを引き回す事もあります。(最近ではほとんど見ないですけどね)
お礼
BellBellさん、ありがとうございます。 >セッションはブラウザなどに依存せず、一定時間残ります。 そうだったのですか、教えていただき有難うございます。 session.cookie_lifetimeやsession.cache_expireということでしょうか? それとも、それらの設定に関係なく残るのでしょうか? 確か自分はcookieを使用させるためsession.use_only_cookiesを設定しています。 >この機能で、セッションが溜まりまくってしまうという事を防いでいます。 ・・・今思ったのですが、こういう認証フォームの場合、認証後はセッションの内容はブラウザを閉じられるまでずっと保持しておくように実装するものなのでしょうか? それとも、認証が終わったら、基本的には削除するものなのでしょうか?
- honoka-cha
- ベストアンサー率54% (40/73)
簡単なログインシステムを作ったことがありますが、 そのときはセッションだけを使いました。 クッキーは気にしませんでした。ま、クッキーは裏で活躍しているわけですが。 ブラウザを終了させても、すぐブラウザ起動すればログイン状態は残っていました。 有る程度時間がたつとセッションは切れます。 その後いちいちログインが切れるのは面倒だ半日ぐらいはログイン状態を残したい という要望がありphp.iniをいじって対応しました。 まずはセッションだけで作ってみてはどうですか。 超むずかしいってことはないと思います。 何か仕様に合わないことがあればそのときあらためて考えるってことにしてみたらどうでしょう
お礼
honoka-chaさん、ありがとうございます。 セッションだけのものは自分も一応作ってはみたのですが、ZendFrameworkなどでは確かRemember_Me()とかいう関数で ブラウザを閉じた後セッションをどの位の期間保持するかのようなものがありまして。 しかし、一般的にはCookieを使っているだろうから、どうなのかなと思いまして。 セッションを使ってログインフォームを作り、認証した後もずっと認証内容を保持していないといけないのかな?と思っているところに、 色々見ているとuserテーブルにActiveカラムとかあったり、上記のようにLogin=OKのようなものを書いている人もいたりでわけが分からなくなりまして質問させていただきました。
- shimix
- ベストアンサー率54% (865/1590)
個人的意見ですが(汗 >$_SESSION['login']=TRUE等を使うのではないかと思っております。 それはありませんね。$_SESSION['user_id']を持ち回ります。でないと、ログインしているユーザー固有の情報が表示出来ません。また$_SESSION['user_id']がなければログインしていないというだけなので、わざわざ$_SESSION['login']などは使いません。 いずれにしても、セッションを使う場合には、ほぼセッションに持たせます。 「ログイン状態を保持」させようとすると、Cookieに(暗号化した)user_idと(ハッシュ化した)パスワードを記録しておかないといけません。若干項目を追加することもありますが、このふたつは必須になりますね。 いくつかのサイトでhttpリクエストヘッダも確認すればわかりますがuser_idについては、けっこう「そのまま」流しているサイトもありますので、セキュリティ要件次第でしょう(サイトの性格に依存)。httpsに移動するときなどは再ログインさせますしね。
お礼
shimixさん、ありがとうございます。 パスワードまで記録しているのですか・・・? それは想像もしませんでした。 重要なものはセッションで認証後破棄し、ログイン状態を示す文字列をセッションかクッキーに入れるのだと勘違いしておりました。 となると、パスワードまで格納する必要性が良く分からなくなってしまったのですが、 ユーザIDとパスワードをページ毎に認証するとかいう実装になるのでしょうか? (だからこそブラウザ閉じた後でも勝手に認証されログイン状態になるのかもしれませんが)
補足
あっ、すみません。 http://php-web.net/nyumon/cookie.html このサイトなど見ると、cookieにパスワードは保存しないとか書かれています。 >このふたつは必須 というのはハッシュ化しているためやや安心だという理解で宜しいのでしょうか?
お礼
JaneDueさん、ご回答ありがとうございます。 なるほど、目から鱗でした。 使い捨てパスワードという発想はありませんでした。 確かにそのような実装であればクッキーにパスワードまで残しても、本当のパスワードを格納するよりも遥かに安心ですね。 有効期限も長めに取れますし。 具体的な実装法までお答え頂き誠に有難うございました。