functional tests中的form_authenticity_token
by Xu Wenhao
又是一个前一阵遇到的很tricky的问题。
Rails2.0中加入了form_authenticity_token来防止部分的cross-site的攻击,ActionView中默认的form_for标签会自动加入类似于
的代码,如果你自己使用form_tag来创建form的话,可以用类似于
<input type="hidden" name="authenticity_token" value="<%= "#{form_authenticity_token}" %>" />
的代码来加入这个隐藏的form中的authenticity_token。
但是手工加入这个token在functional tests中会带来问题,因为functional tests中是把allow_forgery_protection关掉的
可以在environments/test.rb中看到这样的配置
config.action_controller.allow_forgery_protection = false
但是authenticity现在是hardcode在代码中,所以跑functional tests通常会遇到这样的错误
ActionView::TemplateError: No :secret given to the #protect_from_forgery call. Set that or use a session store capable of generating its own keys (Cookie Session Store).
一种解决办法是在view中加入当前all_forgery_protection状态的判断代码,比如
<% if protect_against_forgery? %>
<input type="hidden" name="authenticity_token" value="<%= "#{form_authenticity_token}" %>" />
<% end %>
但是有位同学用了个更巧妙的hook的办法,在test_helper.rb中hook掉form_authenticity_token,如下
module ActionController
module RequestForgeryProtection
def form_authenticity_token
return "form_authenticity_token OVERRIDE!"
end
end
end
我比较喜欢后一种啦。
tags: