これが私のテーブル構造です:
// users
+----+--------+------------------------+------------------+-------------------------------+
| id | name | email | cookie | /* some other columns */ |
+----+--------+------------------------+------------------+-------------------------------|
| 1 | Jack | [email protected] | ojer0f934mf2... | |
| 2 | Peter | [email protected] | ko4398f43043... | |
| 3 | John | [email protected] | 0243hfd348i4... | |
+----+--------+------------------------+------------------+-------------------------------+
cookie
列には、ユーザーのデバイスにも設定される文字列(ユーザーのログインを維持するCookie)が含まれています。ご覧のとおり、ユーザーごとに(Cookieとして)oneという文字列しかありません。したがって、すべてのユーザーのデバイスには同じCookieがあります。
ほとんどのプロのプログラマーが私に言っています:
各デバイスに独自のCookieがある場合は、より安全です(各デバイスのCookieは、他のデバイスのCookieとは異なり、すべてのデバイスの定数Cookieではない必要があります)
さて、なぜですか?すべてのデバイスに同じCookieを使用することの何が問題になっていますか?また、ご覧のとおり、データベースにはCookieのレコードが1つしかありません。したがって、新しいデバイスのレコードを更新すると、以前のデバイスはログアウトされます。
編集:次のシナリオを想像してください(さまざまなデバイスのさまざまなCookieに基づく):
アリスは自宅のコンピューターで私のサイトにログインし、ログインしたままになります。後で彼女は学校のコンピューターにもログインし、終了してもサインアウトしませんが、サインアウトし忘れます。彼女は家に帰り、学校で自分のアカウントからサインアウトしたいと考えています。彼女はそれをどのように行うことができますか?
次のシナリオを想像してみてください:アリスは自宅のコンピューターでサイトにログインし、ログインしたままです。後で学校のコンピューターにもログインしますが、完了したらサインアウトします。彼女が家に帰るとどうなりますか?
このシステムを機能させるには、ログアウト時にcookie
列をNULL
に設定する必要があります。しかし、それは彼女をすべてのデバイスからログアウトさせます。たとえば、携帯電話に継続的にログインしたままにしたい場合、それは非常に迷惑です。したがって、ログアウト時にサーバー側で実際にセッションを無効にする限り(常にそうする必要があります)、これはセキュリティの問題よりもユーザビリティの問題のほうが多くなります。
では、ユーザーごとに複数のセッションを許可した場合、テーブル構造はどのようになりますか?まず、cookie
テーブルからusers
列を削除します。次に、次のようにsessions
という新しいテーブルを作成します。
+------+------------------+
| user | cookie |
+------+------------------+
| 1 | ojer0f934mf2... |
| 2 | ko4398f43043... |
| 2 | 34fjkg3j438t... |
| 3 | 0243hfd348i4... |
+------+------------------+
2番目のユーザーには2つの異なるアクティブセッションがあることに注意してください。
X時間後にセッションを終了できるように、どこかにタイムスタンプがあるはずです。 cookieにmax-ageがある場合でも、セッションの盗難の影響を軽減するために、常にサーバー側もセッションを終了する必要があります。
セッション識別子をデータベースに保存する必要はありません。 PHPの組み込み セッション処理 を使用するだけで、IDの生成やCookieの設定などについて心配する必要はありません。
アリスが忘れた場合に学校からログアウトさせる方法についての編集を確認します。すべてのデバイスからログアウトさせる機能を含めます。たとえば、Facebookには そのような機能 があります。または、それを実装するエネルギーを無駄にしたくない場合は、ユーザーにパスワードを変更するように指示するだけです。適切に実装されたパスワードリセット機能は、とにかくすべてのユーザーのアクティブセッションを終了します。
データベースのセットアップでは、すべてのセッションを終了することは、これを実行することと同じです。
DELETE FROM sessions WHERE user = :id
セッションハイジャック攻撃を使用する方が簡単だからです...
詳細はこちら https://www.owasp.org/index.php/Session_hijacking_attack