2010-06-17 84 views
5

在rails中是否有任何規定允許來自站點的所有AJAX POST請求在沒有authenticity_token的情況下通過?我的jQuery AJAX POST請求在沒有發送真實性令牌的情況下工作(Rails)

我有一個調用控制器方法的Jquery POST ajax調用,但我沒有在其中添加任何真實性代碼,但調用成功。

我ApplicationController中確實有「request_forgery_protection」,我已經在我的環境改變

config.action_controller.consider_all_requests_local 

爲false/development.rb

我還搜查我的代碼,以確保我沒有超載ajaxSend發送真實性令牌。

是否有一些機制可以禁用檢查?現在我不確定我的CSRF保護是否有效。

我正在使用Rails 2.3.5。

更新爲清楚:

function voteup(url, groupid){ 
     $.ajax({ 
     type: "POST", 
     url: "/groups/" + groupid + "/submissions/voteup", 
     data: "url=" + url, 
     dataType: 'text', 
     success: function(data){ 
      var counter = "vote_" + url; 
      $('#vote_' + url.cleanify()).text(" " + data + " "); 
     } 
     }); 
    }; 

我有一個鏈接,然後有一個「HREF調用上面的函數:

<a href='javascript:voteup(param1,param2)'>...</a> 
+0

我記得回答過類似的問題..在這裏找到: http://stackoverflow.com/questions/2725118/rails-request-forgery-protection-settings/2725991#2725991 我想應該是因爲它的本地請求。它不應該從運行在不同端口或不同域上的應用程序發出。例如:如果您的應用程序在localhost:3000上運行,您應該無法從localhost:3001執行ajax POST。 – 2010-06-17 10:52:25

+0

Hi Shripad, 我看到了你的帖子,但是這是怎麼回事?是否存在某種Rails魔法? 在網上看,我仍然看到有人寫關於發送form_authenticity_token的指令,所以如果它是固定的,爲什麼仍然需要這樣做? – 2010-06-18 03:43:57

+0

這與Rails的魔法無關。如果Ajax在域本身內被調用,那麼Ajax將不具有真實性標記。您需要一個真實性標記,而不是用於啓用Ajax才能在您的域中工作,但是需要防止來自其他域的攻擊。這是在應用程序控制器中擁有'protect_from_forgery'的主要原因。來自另一個領域的攻擊的最好例子是「Myspace sammy蠕蟲」。看看它。然後,您將瞭解爲什麼您需要身份驗證令牌。 – 2010-07-05 03:32:29

回答

6

這裏的一個可能的情況是,您使用jQuery序列化一個正常的Rails表單......並且它包含了序列化的auth令牌隱藏字段(Rails將它們添加到所有表單中)。

看看你生成你提交表格源......很可能你會看到

<input name="authenticity_token" type="hidden" value="somethinghere...." /> 

你可以做的另一件事是檢查日誌,看看是否authenticity_token領域是請求參數。

+1

我更新了一些代碼示例的問題。 我的日誌不顯示正在發送的authenticity_token參數。 – 2010-06-17 07:19:55

3

在佈局視圖中添加這樣的:app/views/layouts/(something).html.erb

<% if protect_against_forgery? %> 
<script type="text/javascript" charset="utf-8"> 
    //<![CDATA[ 
    window._auth_token_name = "#{request_forgery_protection_token}"; 
    window._auth_token = "#{form_authenticity_token}"; 
    //]]> 
</script> 
<% end %> 

而在你的application.js:

$.ajaxSetup({ 
    'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/javascript")} 
}); 

$(document).ready(function() { 
// All non-GET requests will add the authenticity token 
// If not already present in the data packet 
$("body").bind('ajaxSend', function(elm, xhr, s) { 
    if (s.type == "GET") return; 
    if (s.data && s.data.match(new RegExp("\\b" + window._auth_token_name + "="))) return; 
    if (s.data) { 
    s.data = s.data + "&"; 
    } else { 
    s.data = ""; 
    // if there was no data, $ didn't set the content-type 
    xhr.setRequestHeader("Content-Type", s.contentType); 
    } 
    s.data = s.data + encodeURIComponent(window._auth_token_name) + "=" + encodeURIComponent(window._auth_token); 
}); 

在你application_controller.rb添加此保證IE/Safari收到正確接受標題:

def correct_safari_and_ie_accept_headers 
    ajax_request_types = [ 'text/javascript', 'application/json', 'text/xml'] 
     request.accepts.sort!{ |x, y| ajax_request_types.include?(y.to_s) ? 1 : -1 } if request.xhr? 
end 

這確保接受標頭默認爲text/javascriptapplication/jsontext/xml而不是默認text/html

現在您可以執行常規的AJAX調用。它會通過身份驗證令牌。另外,請確保僅在CDATA腳本標記之後包含application.js,因爲它需要兩個全局變量window._auth_token_namewindow._auth_token

希望這有助於!乾杯:)

+0

感謝您的代碼,但我的問題是,在這個時候,即使沒有認證令牌,我的帖子也能正常工作。 – 2010-06-17 09:03:15

相關問題