无法验证 CSRF 令牌真实性 Rails 4.1

Posted

技术标签:

【中文标题】无法验证 CSRF 令牌真实性 Rails 4.1【英文标题】:Can't verify CSRF token authenticity Rails 4.1 【发布时间】:2014-06-16 03:46:53 【问题描述】:

我正在开发一个简单的网站,让管理员可以创建问题并让用户解决问题。我将 ActiveAdmin 用于管理部分,将简单的 AJAX 调用用于用户解决部分。起初尝试通过 ActiveAdmin::Devise 登录是成功的,但无法退出。我删除了所有 cookie,从那时起,我无法在没有 CSRF 令牌真实性异常的情况下进行 POST 操作。我的 application.html.erb 的头部有正确的 meta_tags,声明了 jquery_ujs(其他线程说这是一个常见问题),并且在两个 POST 操作中都存在真实性令牌。我什至尝试通过 skip_before_filter :verify_authenticity_token 避免验证,但 ActiveAdmin 登录和 POST 示例继续失败。日志如下,您可以看到令牌存在。我还展示了 Gemfile,以防其中任何一个与 CSRF 发生冲突。

Rails 版本 [4.1.0] Ruby 版本 [2.1] Phusion 乘客版 [4.0.41]

提前致谢。

application.html.erb

<head>
  <title>Introducción Matematicas</title>
  <%= stylesheet_link_tag    "application", media: "all"%>
  <%= javascript_include_tag "application", "data-turbolinks-track" => true %>
  <link href="http://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700|Roboto+Slab:300,400" rel="stylesheet" type="text/css">
  <%= csrf_meta_tags %>
</head>

application.js

//= require jquery
//= require jquery_ujs
//= require_tree ../../../vendor/assets/javascripts/.
//= require_tree .

应用控制器

class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :null_session
  #skip_before_filter :verify_authenticity_token
  before_filter :configure_permitted_parameters, if: :devise_controller?
  protected
  def configure_permitted_parameters
      devise_parameter_sanitizer.for(:sign_up) do |u|
        u.permit :name,:college, :email, :password, :password_confirmation
      end
  end
end

管理员登录日志

INFO -- : Processing by ActiveAdmin::Devise::SessionsController#create as HTML
INFO -- :   Parameters: "utf8"=>"✓", "authenticity_token"=>"aRZK3470X6+FJPANEuHAiwVW4NZwMzCkXtoZ1qlhQ0o=", "admin_user"=>"email"=>"omar@gmail.com", "password"=>"[FILTERED]", "remember_me"=>"0", "commit"=>"Login"
WARN -- : Can't verify CSRF token authenticity
INFO -- : Completed 401 Unauthorized in 110ms
INFO -- : Processing by ActiveAdmin::Devise::SessionsController#new as HTML
INFO -- :   Parameters: "utf8"=>"✓", "authenticity_token"=>"aRZK3470X6+FJPANEuHAiwVW4NZwMzCkXtoZ1qlhQ0o=", "admin_user"=>"email"=>"omar@gmail.com", "password"=>"[FILTERED]", "remember_me"=>"0", "commit"=>"Login"
WARN -- : Can't verify CSRF token authenticity
INFO -- :   Rendered vendor/cache/ruby/2.1.0/bundler/gems/active_admin-a460d8d2ab37/app/views/active_admin/devise/shared/_links.erb (2.0ms)
INFO -- :   Rendered vendor/cache/ruby/2.1.0/bundler/gems/active_admin-a460d8d2ab37/app/views/active_admin/devise/sessions/new.html.erb within layouts/active_admin_logged_out (73.0ms)
INFO -- : Completed 200 OK in 302ms (Views: 80.2ms | ActiveRecord: 0.0ms)

通过 AJAX 日志进行简单 POST

INFO -- : Processing by QuestionsController#check_question as JS
INFO -- :   Parameters: "utf8"=>"✓", "que_id"=>"44", "authenticity_token"=>"CjaAx+B36JPc1PUIhta0vIuOTKX4UhrFWlmYHAd+KWY=", "question"=>"id"=>"169", "commit"=>"Verificar Respuesta", "id"=>"6"
WARN -- : Can't verify CSRF token authenticity
INFO -- :   Rendered answers/_answer.html.erb (1.2ms)
INFO -- :   Rendered questions/check_question.js.erb (17.0ms)
INFO -- : Completed 200 OK in 94ms

宝石文件

source 'https://rubygems.org'
gem 'rails', '4.1.0'
#gem 'ckeditor'
gem 'mysql2', "0.3.15"
gem 'devise'
gem 'activeadmin', github: 'gregbell/active_admin'
gem 'sass-rails', '~> 4.0.0'
gem 'uglifier', '>= 1.3.0'
gem 'execjs'
gem 'therubyracer'
gem 'coffee-rails', '~> 4.0.0'
gem 'jquery-rails'
gem 'turbolinks'
gem 'jbuilder', '~> 1.2'
group :doc do
  gem 'sdoc', require: false
end
gem 'minitest'

【问题讨论】:

类似答案可见here。致谢:@hungyuhei 【参考方案1】:

skip_before_filter :verify_authenticity_token

哇,不要这样做。这完全是黑客攻击,如果你不小心把它留在了代码中,你就会造成严重的安全问题。

那么,为什么要删除 cookie?如果我正确阅读了您的问题,那是因为您的注销功能已损坏?您如何找出注销不起作用的原因并修复它。去创建另一个问题(绕过 CSRF 身份验证)而不是修复原始问题可能不是一个好主意。

与此同时,重新启动本地开发服务器并在浏览器中启动一个新选项卡。看看这是否让 CSRF 的东西至少消失了,然后再回到注销问题。

【讨论】:

skip_before_filter 只是为了检查除了登录之外的其他 POST 操作发生了什么,如果 CSRF 检查被忽略(服务器在本地网络中,只有我的团队可以访问,这就是我使用skip_before_filter hack),正如您的建议,我将首先检查登录和注销操作发生的情况。如果我发现问题,我会在这里发布结果:) 谢谢@jefflunt 哦,我以为它只是在一个内部盒子上。我的意思是,在经过长时间的调试会话后,有时事情会被遗忘,如果它投入生产会很糟糕。 我似乎遇到了同样的问题。如果我已登录(设计),则没有错误。 我在 ActiveAdmin 登录时遇到了同样的问题,我的在服务器上工作了几个月没有任何问题,突然这变成了一个问题,你有没有运气解决这个问题? 这是安全的,如果我们write API .. 对吗?【参考方案2】:

只需添加以下 gem https://github.com/jsanders/angular_rails_csrf 即可完成其余部分。

【讨论】:

【参考方案3】:

通常,您在从 AJAX 调用时会遇到此问题。您可以简单地将令牌与帖子一起发送

headers : 
      'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') // X-CSRF-TOKEN is used for Ruby on Rails Tokens

在你的 ajax post 调用中,并确保你有

<%= csrf_meta_tags %>

在您的 HTML 中。

永远不要使用这个

skip_before_filter :verify_authenticity_token

【讨论】:

以上是关于无法验证 CSRF 令牌真实性 Rails 4.1的主要内容,如果未能解决你的问题,请参考以下文章

Rails 3:无法验证 CSRF 令牌的真实性

无法在 Rails 中验证 CSRF 令牌的真实性

Rails post 无法验证 CSRF 令牌的真实性

Rails:发出 POST 请求时无法验证 CSRF 令牌的真实性

Rails用户登录错误:无法验证CSRF令牌的真实性

即使设置了标头,也无法验证 CSRF 令牌的真实性 Rails 4 Ajax