Rails 2.0の新しいセッション管理-CookieStore

(注)この記事の動作確認環境はRC1です。
以前、Railsはデフォルトでtmp/sessionsにセッションファイルを作り続けるため、sessionsフォルダ内のメンテナンスが必要であるという記事を書きました(こちら)。Rails2.0ではデフォルトでCookieStoreという新しいセッション管理機構を用いるため、上記処理の必要がなくなります。

CookieStoreの特徴

  • クッキーで情報を持つため余分なIOがなくなり高速
  • セッションファイルの管理が不要
  • セッションデータが4kを越える場合はCookieOverflowエラー*1

デフォルト設定

environment.rbを確認すると、以下のような記述が追加されています。

  config.action_controller.session = {
    :session_key => '_application_session',
    :secret      => 'some_random_value'
  }

この設定を用いて、railsはセッション情報をcookieへ格納します。

セッションデータのcookieへの格納

cookie内で、セッションデータは上記session_keyをキーとして以下のように格納されています。

BAh7BzoJeXNlciIJaG9nZSIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6%250ARmxhc2g6OkZsYXNoSGFzaHsABjoKQHVzZWR7AA%253D%253D--8fe60b380b7fe7727a5d3eacc284387644631a22

'--'をセパレータとして、左側にセッションデータ、右側にセッションデータを暗号化(というよりハッシュ化)したものがセットされています。つまり左側を(data)、右側を(digest_date)とすると

(data)--(digest_data)

と言うフォーマットで格納されるわけです。

(data)の生成

セパレータ左側のデータは以下のロジックで生成されています。

Base64.encode64(Marshal.dump(session)).chop

データをmarshalしてbase64エンコードしていることが分かります。(data)の暗号化はされていません。

(digest_data)の生成

セパレータ右側のデータは以下のロジックで生成されています。

OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new(@digest), key, data)

HMACでハッシュ結果を生成しています。dataはセパレータ左側のデータと同じものです。@digestはデフォルトでSHA1が用いられますが、設定により変更できます。例えばSHA256にしたい場合、environment.rb内の設定を以下のようにしてやります。

  config.action_controller.session = {
    :session_key => '_application_session',
    :secret      => 'some_random_value',
    :digest      => 'SHA256'
  }

(data)と(digest_data)

(data)と(digest_data)の内容自体は同じものです。サーバサイドでは(digest_data)をもとにcookieデータの正当性を検証します。secretキーを知らない限り(digest_data)は生成できないので、ユーザによるcookieデータの改竄を防ぐことができます。

運用上の注意

  1. ユーザに見せたくないデータはセッションに格納してはいけません。*2
  2. セッションデータが4kを超えないようにしてください。
  3. (11/28追記)運用環境では:secretの値を変更するなど、秘密鍵の漏洩に注意してください。*3

上記3点にだけ気をつければ、あとは他の格納方法とかわりありません。セッションファイルの管理が不要になると言う大きなメリットがあるため、特段の事情がなければデフォルト設定のままCookieStoreを使用していただいて問題ないでしょう。
なお、第3者へのデータ漏洩を防止するためにはhttpsを用います。これは他の方法でSession管理を行う場合も同様です。CookieStoreを用いるからといって、他の方法と比べて漏洩リスクが格段に高くなるということはありません。*4

*1:セッションでサイズの大きいデータを扱いたい場合は、PStoreやActiveRecordStoreなど他の方法を採用する必要があります。

*2:暗号化されないセッションデータがcookieに保存されるため。secretキーがあるからといって暗号化されたデータのみを扱っているわけではないことに注意!

*3:データベースパスワードと同じくらいの運用をしていただくとよいでしょう。

*4:CookieStoreを使わなくても、session_idはcookieでやりとりされているため。ただし、秘密鍵が明かになるとクッキーが改竄できるので、その点でなりすましのリスクが高まるということは言えるかも知れません。秘密鍵は慎重に管理しましょう。当たり前だけど