2

私はこのコードでレールに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保護を無効にしていないので、トークンの欠落に関するエラーが発生するはずでしたが、そうではありません...

編集:

私が持っている2つの答えを読んだ後:

  • jquery_ui ファイルを削除しました

このコードを追加して、csrf トークンの jquery_ui 関数を置き換え、devise の 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 に関連する create アクションを別のものに置き換えました。

  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これもあなたのbtwとは何の関係もありません。の間違った使い方です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 トークンによってトリガーされる動作は、約 1 年ほど前に変更されました。例外を発生させるのではなく、新しい動作はセッションをリセットすることであるため、リクエストはユーザーがログインしていないかのように処理されます。

handle_unverified_requestそこで目的の動作を定義して実装することで、この動作を制御できます。

于 2012-04-30T13:56:11.763 に答える