2

我正在使用以下代码向 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_ui 文件

添加此代码以替换 csrf 令牌的 jquery_ui 函数,并设置 auth_token 以进行设计:

  $.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);
    }
  });

删除了 before_file authenticate_user!来自控制器,并将与 current_user 相关的创建操作替换为不同的操作:

  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 保护,但我仍然遇到同样的错误......所以问题是另一个问题,但我真的不明白什么会导致双重重定向,因为记录是在数据库中正确创建的......

4

2 回答 2

2

如果您已包含jquery_ujs.js在您的应用程序中,CSRF 令牌将自动添加到 AJAX 请求中。你可以在这里看到。

这也与您的顺便说一句无关DoubleRenderError。那是你对respond_with.

编辑:

不要禁用 CSRF 保护。只是不要。

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

您的操作导致错误的原因是respond_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_with这里

于 2012-04-30T13:48:53.000 回答
0

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

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

于 2012-04-30T13:56:11.763 回答