Rails - 与集成测试和Capybara失去会话 - CSRF相关?

joe*_*lis 14 rspec ruby-on-rails csrf devise capybara

我正在使用Rails 3.1.0.rc4,我正在与capybara的新类似DSL和Rspec进行集成测试(使用Devise身份验证)

我遇到的问题是,当我运行集成测试时,来自capybara的机架测试驱动程序似乎完全失去了用户的登录会话,事实上,会话似乎完全清除了.

经过几天的调试,我完全失去了原因.逐行通过中间件堆栈,我相信我已经把问题排除在ActiveRecord::SessionStore导致这种情况发生的事情上.我在这里读到Rails会清除一个会话,如果它无法验证CSRF令牌,这让我相信我有一些配置错误,并且由于某种原因这个测试没有正确验证CSRF令牌.

这是我在/ initializers目录中的session_store.rb中的内容:

MyApp::Application.config.session_store :active_record_store
Run Code Online (Sandbox Code Playgroud)

有没有人知道铁轨中的CSRF保护有任何线索可能会发生这种情况?

此外,还有一些注意事项:

  • 我试图测试的东西实际上在浏览器本身内工作,只有这一个测试正在放弃会话
  • 在将操作URL提交到另一个服务器的表单后,会话似乎被删除.我正在使用VCR gem来捕获测试中对这个外部服务器的请求/响应,虽然我认为我已经将外部请求作为问题,但这可能与CSRF令牌没有进行身份验证直接相关,从而清理会话.
  • 涉及登录/使用会话的其他测试不会丢弃会话

任何人都可以给我任何关于这里究竟发生了什么的线索,以及为什么一个测试似乎随意地放弃了它的会话而对我失败了?我做了很多调试,并尝试了我能想到的一切.

ari*_*era 20

我也是Capybara的新手,我遇到了类似的问题.

我试图登录用户做这样的事情:

post user_session_path, :user => {:email => user.email, :password => 'superpassword'}
Run Code Online (Sandbox Code Playgroud)

这是正常的,直到我尝试与capybara做一些事情,例如访问页面并测试用户是否已登录.这个简单的测试没有通过:

visit root_path
page.should have_content("logout") #if the user is logged in then the logout link should be present
Run Code Online (Sandbox Code Playgroud)

起初我认为水豚正在清理会议,但我错了.花了我一些时间才意识到的事情是驱动程序capybara正在使用句柄自己的会话,因此,从水豚的角度来看,我的用户从未登录.为此,你必须这样做

page.driver.post user_session_path, :user => {:email => user.email, :password => 'superpassword'}
Run Code Online (Sandbox Code Playgroud)

不确定这是否是你的情况,但希望有所帮助.

  • 好像在后来的水豚中停止工作了.我有一些类似的东西,并且与前1版本相关.现在我升级到2.1,它以这种方式失败了.鉴于这个答案的日期,很可能它自从水豚以来一直在这样工作1.很好的解释! (2认同)

bri*_*ran 7

手动方式非常简单:

it "does something after login" do
  password = "secretpass"
  user = Factory(:user, :password => password)
  visit login_path
  fill_in "Email", :with => user.email
  fill_in "Password", :with => password
  click_button "Log in"
  visit # somewhere else and do something
end
Run Code Online (Sandbox Code Playgroud)

然后,您可以将其分解为'spec_helper.rb'中的函数:

# at the bottom of 'spec_helper.rb'
def make_user_and_login
  password = "secretpass"
  @user = Factory(:user, :password => password)
  visit login_path
  fill_in "Email", :with => @user.email
  fill_in "Password", :with => password
  click_button "Log in"
end
Run Code Online (Sandbox Code Playgroud)

并在任何测试中使用它(可能是请求规范):

it "does something after login" do
  make_user_and_login
  # now test something that requires a logged in user
  # you have access to the @user instance variable
end
Run Code Online (Sandbox Code Playgroud)


Ada*_*ant 5

我能够通过在config/initializers/test.rb中将此值设置为true来修复此错误

# Disable request forgery protection in test environment
config.action_controller.allow_forgery_protection = true
Run Code Online (Sandbox Code Playgroud)

事先,CSRF <meta>标签没有打印到<head>.更改此值后,它们最终会出现.