質問: 前提 -- 先日、以下の質問をさせていただきました。 phpでの認証について その結果、phpでの認証に下記のページに書かれているセッション認証を使えば、 色々とうまくいくということが分かりました。 PHPによる簡単なログイン認証いろいろ セッション認証について色々と調べましたが、腑に落ちない点や、 実装した際に不都合が生じる気がしています。 疑問に思ったこと -------- **1. セッションIDについて** ログイン済みかどうかを下記のように判断していることが一般的なようです。 ``` !isset($_SESSION['username'] ``` ここで、クライアント側で適当なセッションIDを用いて usernameが保存されているセッションをCOOKIE?に故意に作成することができれば、 usernameの値さえ変えれば、好きなユーザーとしてログインした状態を作れるような気がしています。 そこで、セッションIDを生成したタイミングで、そのセッションIDをサーバー側で保持し、 毎回usernameとセッションIDを照合することで乗っ取りは防げるのではと思いました。 ただ、そこで2番目の疑問が生じました。 **2. 複数端末でのログインについて** google, facebookなど、複数端末でログインできるようなサービスはたくさんあります。 上記のように、usernameとセッションIDを照合する仕組みで実装した場合、 ログインごとにセッションIDが変更されてしまうため、 端末Aでログイン後、端末BでログインをするとセッションIDが変更され、 端末Aはログアウト状態になってしまうと考えました。 そこで、usernameとpasswordによる認証が成功したタイミングで、 usernameとサーバー側で保持している文字列を使ってハッシュ値を生成すれば、 複数端末で同じハッシュ値が生成され、認証を行うことができるような気がしています。 ただ、これではハッシュ値が固定値となってしまうため、セキュリティ的に問題がある気もしています。 上記を踏まえて ------- 以上のことから、現状ではusernameとサーバー側で保持している文字列からハッシュ値を生成し、 それを認証で使う方法が最も効果的なのではと考えています。 これに対して、問題があればご指摘をいただきたいです。 また、上記の記述の中に間違っている認識があれば教えていただきたいです。 まだまだ勉強を始めたばかりで、説明部分で意味が通じていない箇所もあるかと思いますが、 ご意見いただけると幸いです。 よろしくお願いいたします。
回答: うーん、まずはご自身で仕様を確認し、試されるのがいいかと思いますよ。 参考URL どのような値がセッションIDとしてcookieに保存されているのか、 HTTPリクエストヘッダとしてこれがどう送られるのか、 サーバ側でどのように$_SESSIONが扱われているのか。 この辺に想像や推測が混ざっていると、会話の前提が成り立ちません。 ブラウザ→サーバの値や挙動は chromeなら開発者ツール firefoxならfirebug といったツールを使用することで詳細に確認できます。 簡単に回答すると > > usernameが保存されているセッションをCOOKIE?に故意に作成することができれば、 > > usernameの値さえ変えれば、好きなユーザーとしてログインした状態を作れるような気がしています。 > > > ユーザIDとsessionIDには相関関係が存在しないこと、かつセッションIDは十分に長い文字列であるため、任意のユーザのセッションIDを狙って作ることは非常に困難だという前提に成り立っています。 これが覆されるケースとしては、 ・cookieが何らかの理由で漏れた場合 ・通信経路が暗号化されておらず、セッションIDが途中でキャプチャされた場合 ・サーバ側でセッションIDが漏れた場合 ・無限回の試行が可能な場合 です。 これらのケースの場合、クライアント側からのリクエストを信じるという仕組みである限り、 どんな方法でセッションIDを発行しても同じです。 そのため、 > > そこで、セッションIDを生成したタイミングで、そのセッションIDをサーバー側で保持し、 > > 毎回usernameとセッションIDを照合することで乗っ取りは防げるのではと思いました。 > > > をしたとしても、usernameも一緒に漏れることになるので意味がありません。 *これに対応しようとすると、 クライアント側が詐称した場合に通信が成り立たなくなるソースIPアドレス等を絡ませる、 SMSやメールを使って多段階認証をするなどのHTTP以外の方法で認証情報をやり取りする といった方法が必要になってきます。 上記の理由から、 特に多重ログイン防止について何も考えずに作ると、 複数個所からのログインが出来るように出来上がります。 簡単なものでいいので、一度ログイン機能だけを持ったwebアプリケーションを作ってみることをお勧めします。