使用Rspec / Capybara,如何在访问表单后擦除“浏览器”会话cookie以模拟CSRF错误的常见原因

问题描述

我们网站上的一个表单页面偶尔会不一致地显示很多ActionController :: InvalidAuthenticityToken错误

查看日志,我们可以看到以下情况发生:

a)用户访问表单(作品) b)单击一个选项(有效) c)几天后单击另一个选项(导致CSRF错误

我们认为问题在于(b)用户退出浏览器后,这会删除会话cookie,然后,如果在浏览器中启用了“重新打开页面”,则当他们重新打开浏览器时,它将重新显示页面,但没有会话,因此会话中缺少预期的CSRF令牌。

我们添加了一些代码来处理带有自定义错误消息的特定CSRF错误

我们想通过模拟相同的事件序列来测试rspec中的新代码

这需要一种方法来擦除该用户的Capybara会话,模拟在关闭浏览器然后重新打开时发生的情况。

visit form_url
click_button button_a
?? erase session cookie,with page object still 'open',so form object still exists??
click_button button_b

使用reset_session!也会擦除页面对象。

在Rspec规范中,我们如何删除/使“浏览器”会话cookie无效,以便当我们单击表单上的另一个按钮时,将触发Rails CSRF错误

解决方法

我认为有一个简单的方法可以做到这一点,即向Rails后端发出请求。较高的层次是您将路由和控制器操作公开给测试模式,而在其他任何环境中都不会公开。

在您要清除会话cookie的特定情况下,需要对此端点进行请求。

在控制器操作中,清除会话cookie并进行设置,以使刚发出的请求不会设置新的会话

# config/routes.rb
get 'clear-session',:to => 'application#__clear_session' if Rails.env.test?

# controllers/application.rb

if Rails.env.test?
  def __clear_session
    request.session_options[:skip] = true
    cookies['__yourapp_session'] = { :value => '',:expires => Time.at(0) }
  end
end