ゲーム攻略からプログラミングまで、その時に思いついたことをだらだらと書き連ねていきます。

【Rails】外部からPOSTされてくるデータの扱いについて

2015.01.18 10:01 | コメント(0) | 技術

program.jpg
Rails 2.x系のお話です。

どうも、さつきさん on Railsです。
レールが敷かれた人生なんてまっぴらだよ!

※この記事は、過去にお友達のブログネタに寄稿したものを加筆・修正したものです。
 ゴーストライターというほど大層なことは書いてないんですが、
 この度友人がブログを終了するとのことで、お引越しさせていただきます。


3.x系以降はちょっと記述が変わってるので、その辺はまあ・・・
上手いこと工夫してください
この記事はRails 2.3.11(確か)、Ruby 1.8.7(たぶん)の環境を想定して書いてます。
雑ですいません。

自分がハマったのでメモ程度に。
前回の記事こっちから外部へPOSTする際の問題でしたが、
今回は外部からPOSTされてくる場合です。

まずはauthenticity_tokenの説明から。
authenticity_token
CSRF(Cross-Site Request Forgeries)を防止する目的で設置されたRailsの機能。
GET以外のメソッドでリクエストがあった場合(POST、PUT、DELETE)に、
セッションに格納されたauthenticity_tokenと渡ってきたパラメータの文字列を比較して、同じ値であれば通すという代物。
中身はこんな感じ「rsD/RawxJwfZv1ZIv1r8Pdl1wGQolUH5A/r2OcQQ5Q4=
CSRFについては、この辺でお勉強してみてください。

(でもauthenticity_tokenなんて設定した憶えがないし、viewに表示されてないじゃん。)

ソースを見てみると、フォームを作成した後にこっそりhiddenでついてきてます。
※当然RailsのFormHelperを用いて作成した場合に限ります。

一見ありがたい機能に見えますが、これがなかなか厄介。
ちょっと問題があるケースと、回避策を説明しますね。

問題があるケース

例えば別サイトからPOSTされたデータをRailsの特定のアクションで処理する場合。
特になにもしなければInvalidAuthenticityTokenというエラーが出るでしょう。

これは「渡ってきた値が違うよ!よ!」って言ってます。


対策しましょう

Javascriptを使って値を取り出す方法なんかもありますが、
Rails内の記述をちょこっと触るだけで解決できちゃうので、こっちを紹介します。

記述箇所

まずauthenticity_tokenがどこで設定されているかと言うと、
#{RAILS_ROOT}/app/controllers/application_controller.rbの中にこんな記述があります。
protect_from_forgery #:secret => "・・・"
要はこの子を特定のactionの時にだけ通らないようにすればいいんです。
※コメントアウトはそのままで大丈夫です。

特定のアクションだけauthenticity_tokenを無効にする

で、その方法がこれ。
protect_from_forgery :except => [:action_name]

これだけ。

ね、簡単でしょ?(ボブ・ロス
上記の記述を除外したいアクションがあるコントローラに記述してあげるだけです。
例)Hogeコントローラのreceive_dataアクションを除外したいとき。
class HogeController < ApplicationController

protect_from_forgery :except => [:receive_data]

def receive_data
~にょろにょろ~
end
end

こんな感じ。
filterに似たような感じで使えます。

他にも:onlyを使って特定のactionにのみ使うことも出来ます。

あとがき

普段は便利なんですけどいざ外すとなるとなかなかうまくいかないものですね。
まあこんなふうにご丁寧に逃げ方まで書いてくれてるので親切といえば親切なのかな?

ちなみにviewからauthenticity_tokenを確認したい場合は、
<%= form_authenticity_token %>

でオッケー。
なんか数字が出てきます。

CSRFRailsのAuthenticityTokenの機能について理解していたら、
こんなところで詰まらないとは思うのですが、
最初っからフレームワーク側で考慮されている場合、なかなか気づきにくいものです。
私も初めて見たときは、

なんなんだ!このエラーは!

と思いましたw
ご参考になれば幸いです。
ではではー。
技術の記事

コメント

まだコメントがありません...(´・ω・`)