2012-04-30 19 views
2

我正在一個AJAX POST請求,使用此代碼導軌:Rails和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保護,所以應該有鑑於有關令牌丟失的錯誤,但它有沒有...

編輯:readng兩個答案後

我:

  • 刪除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保護,但我仍然得到同樣的錯誤......所以,萬阿英,蔣達清是另一個但我真的不明白什麼會導致雙重定向,因爲記錄在數據庫中正確創建...

+0

我不認爲這個錯誤與csrf有關。哪一行是第26行(回溯提到的行) –

+0

是的,我剛剛發現它與respond_with的語法有關,我在這裏使用了與format.json相同的語法,但它似乎不是同...抱歉的時候,你已經失去了 –

回答

2

如果您已將jquery_ujs.js包含到您的應用程序中,CSRF令牌將自動添加到AJAX請求中。你可以看到here

這也與你的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的更多細節是here

+0

確定,但: 1)我讀了滑軌顯示HTTP頭作爲參數,但我看不到在請求的PARAMS –

+0

的X-CSRF令牌參數它是標題,而不是參數。爲此目的使用瀏覽器的開發工具:默認情況下,Rails日誌不包含標題。 – jdoe

+0

您可以通過'request.headers ['X-CSRF-Token']'獲得CSRF標記。標題不是參數的一部分。 – iain

0

由於丟失或無效的csrf標記觸發的行爲約在一年前發生變化。新的行爲是重置會話,因此請求處理就像用戶未登錄一樣。

您可以通過定義handle_unverified_request並在其中實現所需的行爲來控制此行爲。

+0

但@iain在他的回答中指出,因爲我使用(當然,僅將其插入) jquery_ujs.js它應該自動包含teh標記...雖然它不會引發異常,但它不應該保存記錄,對吧? –

+0

你是對的,@MatteoPagliazzi – iain

+0

我已經更新了更多的細節問題.. –