InvalidAuthenticityTokenエラー

Tipsというより現象記録的なメモですが、「ActionController::InvalidAuthenticityToken」というエラーが出ることがあります。Rails2.0はデフォルトで CSRF(クロスサイトリクエストフォージェリ)対策がとられているわけですが、これに違反したときにでるエラーなようです。

CSRFとは

 Webサイトにスクリプトや自動転送(HTTPリダイレクト)を仕込むことによって、閲覧者に意図せず別のWebサイト上で何らかの操作(掲示板への書き込みなど)を行なわせる攻撃手法。
 ユーザはCSRFの仕込まれたサイトにアクセスすることによって、特定の掲示板やアンケートなどに書き込まされたり、オンラインショップで買い物をさせられたりしてしまう。ブラウザでアクセスしただけで実行されてしまうため、ユーザが閲覧前に危険が無いかを調べて回避するのは現実的には難しい。

http://e-words.jp/w/CSRF.html

CSRFへの対策

 サーバ側でCSRFを防ぐには、サイト外からのリクエストの受信を拒否する必要がある。ヘッダに含まれる情報を元に参照元が正規のページかどうかをチェックしたり、フォームの一部にランダムな数値を隠しておいてアクセスの一貫性をチェックしたり、コンピュータが読み取れないよう画像として表示したチェックコードの入力をユーザに要求するなどの手法があり、これらを組み合わせて対策を講じる必要がある。

http://e-words.jp/w/CSRF.html

Rails2.0の場合

Railsはこの「フォームの一部にランダムな数値を隠しておいてアクセスの一貫性をチェック」をデフォルトで行ってくれるわけで、フォームから送られてくる「authenticity_token」とセッションの値(正確なところは参考のところのページを見てね)が違っていると、「ちゃんとした認証を経た結果としてフォームが送られた」と見なさず、エラーを出すわけです。

エラーが出るとき

というように通常の使い方だとこういうケースで出るエラーですが、テスト的にアプリケーション・フォルダを丸ごとコピーして別フォルダにして、それぞれをポート番号を変えて複数起動させるとこのエラーが出ることがあります。
それはきっと「/config/environment.rb」のなかの sessionの記述が丸ごとコピーなので同じになっていて、Cookieを使ったセッション管理がバッティングしているためだと思います。

 config.action_controller.session = {
    :session_key => '_myapp_session',
    :secret      => '4713d1fa15263a611f698a470・・・0446cb03169cc4a83b42d7b'
  }

参考

  1. この件について、こちら(→Ruby On Rails ピチカート街道 - -)が超詳しいです。
  2. 正しくCSRF対策を回避する方法は、こちら(→http://d.hatena.ne.jp/namako2007/20080103/1199325817)が参考になります。