2012-04-30 4 views
2

я Создание запроса AJAX POST на рельсы с этим кодом:Рельсы и запрос ajax: не работает csrf?

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 поэтому он должен иметь учитывая ошибки о пропавших лексемы, но это не имеет ...

EDIT:

после readng двух ответов у меня есть:

  • удален файл jquery_ui

Этот код заменил функцию jquery_ui для токена csrf и установил также 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, но я все еще получаю ту же ошибку ... так probelm еще один, но я действительно не могу понять, что может вызвать двойное перенаправление, так как запись правильно создана в базе данных ...

+0

Я не думаю, что ошибка связана с csrf. Какая строка - строка 26 (строка, на которую ссылается обратная сторона) –

+0

Да, я только что обнаружил, что это с синтаксисом response_with, я использовал здесь тот же синтаксис, который я использовал с format.json, но кажется, что это не то же ... извините за то, что вы проиграли –

ответ

2

Если вы включили в приложение jquery_ujs.js, токен CSRF будет автоматически добавлен в запросы AJAX. Вы можете видеть это here.

Это также не имеет никакого отношения к вашему DoubleRenderError кстати. Это ваше неправильное использование respond_with.

Edit:

Не отключить защиту 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: here.

+0

ok но: 1-) Я прочитал, что рельсы отображают заголовки http как параметры, но я не вижу параметры X-CSRF-токена в параметрах запроса –

+0

Это ГОЛОВА, а не ПАРАМЕТР. Для этого используйте средство разработки вашего браузера: Rails-журнал по умолчанию не включает заголовки. – jdoe

+0

Вы можете получить токен CSRF с 'request.headers ['X-CSRF-Token']'. Заголовки не являются частью параметров. – iain

0

Поведение, вызванное отсутствующим или недействительным токеном csrf, изменилось примерно год назад.Вместо того, чтобы создавать исключение, новое поведение заключается в сбросе сеанса, поэтому запрос обрабатывается так, как если бы пользователь не вошел в систему.

Вы можете управлять этим поведением, указав handle_unverified_request и реализуя там желаемое поведение.

+0

, который кажется моим делом, но как @iain указал в его ответе, так как я использую (ну, только вставляя его) jquery_ujs.js он должен включать токен автоматически ... и пока он не поднимается и исключение, он не должен сохранять запись, верно? –

+0

Вы правы, @MatteoPagliazzi – iain

+0

Я обновил вопрос более подробно .. –

Смежные вопросы