こんな感じの構成を想定してます
- セッションデータ保存用データベース:Redisやmemcacheなど
- セッションID:Cookieに保存
セッションの仕組み
Cookieに保存されたセッションIDとサーバーが持っているセッションIDを比較して一致しているものがあったらユーザーがログイン済みと判断します。
ログインまでのフロー
- ログインしていない状態ではユーザーはセッションIDを持っていません。このためまずユーザーにフォームなどでIDやパスワードなどでログインを求めます。
- 認証が成功したらサーバーはセッションIDを作成します。生成するセッションIDは他のユーザーが推測しにくい様に長いランダムなものを使用します。
- セッションIDとユーザー情報を紐付ける為に、生成したセッションIDとユーザーIDをペアにしたデータをRedisなどのデータベースに保存します。
- 生成したセッションIDをCookieに保存します。
なぜセッション用のデータベースにRedisやmemcacheを使うのか
セッション情報はユーザーがアクセスするたびに参照する為高速に処理できる必要があります。
このためセッションIDが存在するか、存在する場合はそれに紐づくユーザーIDなどの情報を高速に知ることができるデータベースが適しているので、key-value storeと呼ばれるデータベースがよく使われます。
key-value storeとは
キーを指定して値を取りだすことができるデータベースでNoSQLの一つです。 プログラミングでよく使われるhashやdictionaryのような感じでアクセスできます。
Cookieにセッション情報を保存してはダメなの?
やめましょう。
セッション情報がユーザーに見られたり書き換えられたりします
セッションの中にユーザーIDなどを保存することがあると思いますが、ユーザーIDが連番で振られていると他ユーザーのIDが予測可能なので、悪意のあるユーザーがIDを他の人のユーザーIDに書き換えてログインできてしまいます。
たとえセッションのデータを暗号化していても、使用している暗号化方式の脆弱性が発見されたりすると同じことが起こる可能性があります。
セッション情報が復元されてしまう
セッションにユーザーの状態を保存していると、悪意のあるユーザーが現在のセッション状態を手元に保存しておき、状態が変わった後に以前の状態のCookieに書き戻して状態を戻すことができてしまいます。
セッションをサーバーの都合で切ることができる
Cookieにセッション情報を保存している場合だと、上のセッション情報が戻せてしまうという理由からサーバー側がセッションを切ろうとしても切るのが難しくなります。
セキュリティ
セッションはhttpsで使う
セッションIDはCookieに保存しています。 Cookieはヘッダーに入って送信されるので、暗号化されていないhttp通信だと通信の途中に悪意のあるルーターなどがいたらセッションIDが抜き取られ不正にログインされてしまうので必ずhttpsにしましょう。
secure属性を設定する
Cookieにこの属性をつけると、httpsの通信時にしかCookieを送信しなくなります。 同じドメインのhttpのリンクがあったりすると、httpでアクセスしてしまいCookieが読み取られてしまう可能性があるのでsecure属性をつけておきましょう。
httpでのアクセスをhttpsにリダイレクトするようにしていても最初のアクセスでもCookieが送られてしまうのでNGです。
httponly属性を設定する
この属性をつけることでjavascriptからCookieを読み込むことができなくなります。 クロスサイトスクリプティング(XSS)などで不正なjavascriptを実行されてもSession IDが取得できないのでリスクを減らせます。