Ruby on rails Rails和ajax请求:不使用csrf工作吗?

Ruby on rails Rails和ajax请求:不使用csrf工作吗?,ruby-on-rails,ajax,post,csrf,csrf-protection,Ruby On Rails,Ajax,Post,Csrf,Csrf Protection,我使用以下代码向rails发出AJAX POST请求: var new_note = { title: "New note" }; $.post('/notes.json', { auth_token: auth_token, note: new_note }, function(data, textStatus, jqXHR){ console.log(textStatus); console.log(

我使用以下代码向rails发出AJAX POST请求:

  var new_note = {
    title: "New note"
  };
  $.post('/notes.json',
    {
      auth_token: auth_token,
      note: new_note
    },
    function(data, textStatus, jqXHR){
      console.log(textStatus);
      console.log(jqXHR);
      var createdNoteIndex = self.notes.push(new Note());
      self.openNote(self.notes()[createdNoteIndex - 1]);
    }, "json")
    .error(function(jqXHR, textStatus, errorThrown){
      alert("error");
      console.log(jqXHR);
      console.log(textStatus);
      console.log(errorThrown);
    });
我忘记插入csrf令牌,因此我认为创建操作将失败:

  # POST /notes.json
  def create
    @note = current_user.notes.new(params[:note])

      if @note.save
        respond_with { render json: @note, status: :created, location: @note }
      else
        respond_with { render json: @note.errors, status: :unprocessable_entity }
      end
  end
但数据库中的记录已创建,而请求的记录以500错误结束:

Started POST "/notes.json" for 127.0.0.1 at 2012-04-30 15:26:33 +0200
Processing by NotesController#create as JSON
  Parameters: {"auth_token"=>"zJzKxPnvx5dQDTcFWi5k", "note"=>{"title"=>"New note"}}
MONGODB (0ms) taccuino_development['users'].find({:_id=>BSON::ObjectId('4f9c670a809ad20869000002')}).limit(-1).sort([[:_id, :asc]])
MONGODB (0ms) taccuino_development['notes'].insert([{"_id"=>BSON::ObjectId('4f9e9309809ad223f5000007'), "title"=>"New note", "user_id"=>BSON::ObjectId('4f9c670a809ad20869000002')}])
Completed 500 Internal Server Error in 8ms

AbstractController::DoubleRenderError (Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return".):
  app/controllers/notes_controller.rb:26:in `create'


  Rendered /home/matteo/.rvm/gems/ruby-1.9.3-p194/gems/actionpack-3.2.3/lib/action_dispatch/middleware/templates/rescues/_trace.erb (4.2ms)
  Rendered /home/matteo/.rvm/gems/ruby-1.9.3-p194/gems/actionpack-3.2.3/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (1.5ms)
  Rendered /home/matteo/.rvm/gems/ruby-1.9.3-p194/gems/actionpack-3.2.3/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (14.8ms)
我没有禁用csrf保护,所以它应该给出一个关于令牌丢失的错误,但它没有

编辑:

读完这两个答案后,我得到了:

  • 删除了jquery\u ui文件
添加此代码以替换csrf令牌的jquery_ui函数,并为Desive设置auth_令牌:

  $.ajaxSetup({
    beforeSend: function(xhr, settings) {
      if (settings.crossDomain) return;              
      var csrf_token = $('meta[name="csrf-token"]').attr('content');
      var auth_token = $('meta[name="auth_token"]').attr('content');

      xhr.setRequestHeader('X-CSRF-Token', csrf_token);
      xhr.setRequestHeader('auth_token', auth_token);
    }
  });
删除了\u文件之前的\u用户身份验证!并将关联到当前用户的创建操作替换为其他操作:

  def create
    @note = Note.new(params[:note])

      if @note.save
        respond_with { render json: @note, status: :created }
      else
        respond_with { render json: @note.errors, status: :unprocessable_entity }
      end
  end

然后我禁用了CSRF保护,但我仍然得到相同的错误。。。所以问题是另一个,但我真的不明白什么会导致双重重定向,因为记录是在数据库中正确创建的…

如果您在应用程序中包含了
jquery\u ujs.js
,CSRF令牌将自动添加到AJAX请求中。你可以看到

这也与您的
双渲染器无关。顺便说一句,这是您对
respond\u with
的错误使用

编辑:

不要禁用CSRF保护。别这样

您不需要自己添加令牌,一切都应该自动进行

您的操作导致错误的原因是
respond\u with
。如果您只响应json请求,那么它应该是这样的:

# POST /notes.json
def create
  @note = current_user.notes.new(params[:note])

  if @note.save
    render json: @note, status: :created, location: @note
  else
    render json: @note.errors, status: :unprocessable_entity
  end
end
但是,因为Rails已经知道这种模式(这是一种惯例),您可以将其缩短为:

respond_to :json #, :html, :xml (optionally)

def create
  @note = current_user.notes.create(params[:note])
  respond_with @note
end

有关
respond\u with
的更多详细信息,请参见。

由丢失或无效的csrf令牌触发的行为在大约一年前发生了变化。新的行为不是引发异常,而是重置会话,因此处理请求时就好像用户未登录一样


您可以通过定义
handle_unverified_request
并在那里实现所需的行为来控制此行为。

ok but:1-)我了解到rails将http头显示为参数,但在请求的paramsIt头中看不到X-CSRF-Token参数,而不是参数。为此,请使用浏览器的开发工具:Rails日志默认不包含标题。您可以使用
request.headers['X-CSRF-token']
获取CSRF令牌。标题不是参数的一部分。这似乎是我的情况,但正如@iain在他的回答中指出的,因为我正在使用(好吧,只是插入它)jquery_ujs.js,它应该自动包含令牌。。。虽然它不会引发异常,但它不应该保存记录,对吗?我认为这个错误根本与csrf无关。哪一行是第26行(回溯提到的那一行)是的,我刚刚发现它的语法是respond_with,我在这里使用了与format.json相同的语法,但似乎它不一样。。。对不起,耽误了你的时间