2014年6月5日木曜日

Sinatra・PadrinoでセッションIDを変更する

Webアプリケーションでは例えばログインやログアウトしたタイミングなど、セッションハイジャックのリスクを下げるためにセッションIDを変更したほうがよい場面があります。

PHPですと、言語に組み込みでsession_regenerate_idという関数が用意されています。さすがWebに特化した言語ですね。

で、Rubyでは言語そのものにセッションIDを変更する方法はありません。各フレームワーク依存ですね。ということで、軽量フレームワークとしてよく使われるSinatraやその派生のPadrinoにおいてセッションIDを変更する方法を調べてみました。

ます、セッション内容を破棄して構わないのであれば、

session.destroy

と単にdestoryメソッドを呼んでセッションを破棄するだけです。自動的に新しいセッションIDでセッションが再生成されます。

セッション内容を引き継ぎたい場合は、事前にセッション内容を取得しておき、
新しいセッションの内容としてまるごと置き換えます。

old_session_hash = session.to_hash
session.destroy
session.replace(old_session_hash)

Padrinoの場合、以下の様な感じでヘルパーメソッドにしておくとよいでしょう。メソッド名はphpのマネです。ヘルパーを定義している部分に適当に追加すればいいと思います。

# セッションIDを再生成する
# @return [void]
def session_regenerate_id
  old_session_hash = session.to_hash
  session.destroy
  session.replace(old_session_hash)
end

上記 session_regenerate_id を呼べば、セッションIDが変更されてセッション内容が引き継がれます。

※2014/06/12追記
RackミドルウェアでCSRF対策をしている場合には、セッションIDの変更とともに、セッション内に保持しているCSRFトークンも変更したいと思うでしょう。そういう時は、引き継ぐセッション情報からCSRFトークンの情報を削っておくと、自動的にCSRFトークンを再生成してくれます。ということで修正したコードを載せておきます。

# セッションIDを再生成する
# @return [void]
def session_regenerate_id
  old_session_hash = session.to_hash
  old_session_hash.delete('csrf')
  session.destroy
  session.replace(old_session_hash)
end

上記の例はCSRFトークンをセッションに格納する際のキーが"csrf"である場合です。このキーは状況に応じて変更してください。

※この記事について指摘・意見・提案・感想などありましたら下のコメント欄にどうぞ。

0 件のコメント:

コメントを投稿