りばーさいだー

気ままに書いてみます

protect_from_forgery と callback の関係を調べてみた

発端

某システムにて Rails のバージョンアップをする機会がありまして。

調べてみると、 Rails 5.0 からは protect_from_forgeryデフォルト挙動が変わる と言うじゃないですか。

内容は

protect_from_forgeryのprependのデフォルトをfalseに変更。

ですか。つまり、

今までは controller のどこに protect_from_forgery と書いても callbacks の一番上に積まれていたのが、デフォルトではそうではなくなる

ということですか。

なるほど、これは取り急ぎは既存のままの挙動と合わせたいぞ、という気持ちになりますね。

というのが調べる発端でした。

見てみる

そもそも 4.2 ではどうなんでしょうか。Rails のソースを見てみましょう

def protect_from_forgery(options = {})
  self.forgery_protection_strategy = protection_method_class(options[:with] || :null_session)
  self.request_forgery_protection_token ||= :authenticity_token
  prepend_before_action :verify_authenticity_token, options
  append_after_action :verify_same_origin_request
end

なるほど、特別 options には手を加えずに prepend_before_action を呼んでいる、と。

じゃあ こいつは何してんですか というと

define_method "prepend_#{callback}_action" do |*names, &blk|
  _insert_callbacks(names, blk) do |name, options|
    set_callback(:process_action, callback, name, options.merge(:prepend => true))
  end
end
alias_method :"prepend_#{callback}_filter", :"prepend_#{callback}_action"

なるほど。

ちょっとメタメタしいですが、上の before_action の definition と見比べるにどうやら options.merge(:prepend => true) した上で before_action しているだけのようですね。

4.2 はわかりました。じゃあ 5.0 は どうなんですか

def protect_from_forgery(options = {})
  options = options.reverse_merge(prepend: false)

  self.forgery_protection_strategy = protection_method_class(options[:with] || :null_session)
  self.request_forgery_protection_token ||= :authenticity_token
  before_action :verify_authenticity_token, options
  append_after_action :verify_same_origin_request
end

options.reverse_merge(prepend: false) ですか。prepend が無ければデフォルトで false になるんですね。

で、あとはその options でそのまま before_action していると。

結論

少し冗長ですが 4.2 のうちに protect_from_forgery prepend: true と書いてしまっておいて問題ないですね。

この変更が無いと好きな順番で protect_from_forgery を差し込みたい、という時に困りそうなので、良い変更ですね。


いやはやそれにしても、この 5.2 beta2 が出たというタイミングで焦って 5.0 へのアップデートをしているサービスなんてあるんでしょうかね。滑り込みアウトってところですよね。

そんなタイミングで書いてもアレな記事ネタですが、protect_from_forgery にちょっと自信がついたので良いとします。

今後もちょいちょい書いていければと思います、よろしくどうぞ。