2012-10-24 61 views
5

我有一個單一頁面的應用程序使用CORS認證到另一個域。所有的請求都是JSON請求。「警告:無法驗證CSRF令牌真實性」錯誤 - CORS與設計和:token_authenticatable

我的應用程序可以驗證正常,並可以使GET請求正常。身份驗證正在使用token_authenticatable。即所有請求追加

所以,我的實際問題是,當我嘗試做一個PUT請求,我收到了警告「的auth_token =什麼?」:無法驗證CSRF令牌真實性在軌消息日誌以及一個CanCan :: AccessDenied(您無權訪問此頁面。)異常。

只需在軌道控制器中添加skip_before_filter :verify_authenticity_token即可解決問題。

因此,我只能得出結論,我的ajax請求發送無效或空的csrf_token。

我真的不明白這是怎麼回事,因爲我相信我正確地發送X-CSRF-Token頭與每個Ajax請求正確。

基本上,我的應用程序進行認證,並設計回送一個的auth_token和csrf_token:

render :status => 200, :json => { 
    :auth_token => @user.authentication_token, 
    :csrf_token => form_authenticity_token 
} 

我然後這些令牌存儲在我的AJAX應用程序,並在jQuery中使用ajaxSend,設定,讓jQuery的經過這些令牌與每個請求:

initialize: -> 
    @bindTo $(document), 'ajaxSend', @appendTokensToRequest 

appendTokensToRequest: (event, jqXHR, options) -> 
    if not @authToken? then return 

    if @csrfToken? 
    jqXHR.setRequestHeader 'X-CSRF-Token', @csrfToken 

    if options.type is 'POST' 
    options.data = options.data + (if options.data.match(/\=/) then '&' else '') + 
    $.param auth_token:@authToken 
    else 
    options.url = options.url + (if options.url.match(/\?/) then '&' else '?') + 
    $.param auth_token:@authToken 

我然後可以在鉻網絡標籤看到,對於每個GET請求被髮送的auth_token PARAM,以及所述X-CSRF-Token報頭。

在PUT請求,但它似乎並沒有工作。

我的理論是CORS正在搗亂。如果您提出CORS請求,您的瀏覽器實際上首先會提出附加 OPTIONS請求,以檢查您是否有權訪問此資源。

我懷疑是OPTIONS請求沒有通過X-CSRF-Token頭,因此rails立即使rails端的csrf_token失效。然後,當jQuery發出實際的PUT請求時,它傳遞的csrf_token不再有效。

難道這是問題嗎?

我該怎麼做才能證明這一點? Chrome似乎沒有向我展示網絡標籤中的OPTIONS請求,以幫助我調試問題。

這不是一個大問題,因爲我可以把CSRF的東西關掉。但我想知道爲什麼它不起作用。

回答

0

在Rails中,每個表單提交都需要CSRF令牌的真實性。 它用於安全地提交表單。 當我們打開我們的應用程序時,CSRF標記(每次)將在rails中新建。 如果CSRF令牌未傳遞到控制器內,則此警告將顯示。 我們需要在所有表單提交中傳遞此令牌。

+0

是的,我知道我需要通過CSRF令牌。我確實說過我是通過X-CSRF-Token標頭的方式傳遞它的。所以我不知道爲什麼我會得到WARNING消息。我認爲這可能與OPTIONS請求有關,該請求似乎沒有該頭文件。 – asgeo1

1

我認爲你需要處理OPTIONS請求,該請求應該使用允許CORS請求的各種頭部響應,IIRC他們是訪問控制允許方法,訪問控制允許來源和訪問控制,允許報頭。由於OPTIONS請求失敗,PUT請求可能不會發生。

+0

好吧,我再次看到你的PUT請求正在發生。無論如何,我會試試這個。也許OPTIONS請求使令牌無效,我個人不確定Rails。但也許OPTIONS響應可能會發送新的令牌以某種方式使用。 – jamiebarrow

1

我剛碰到同樣的問題。問題是無法在CORS中發送_session_id cookie。因此,當Rails嘗試驗證令牌時,session[:_csrf_token]null,並且在比較之前Rails會生成一個新的令牌。

要解決此問題,您需要在CORS中啓用cookie發送。這裏是Mozilla Developer Network reference。在服務器和客戶端都需要工作才能使其工作。

客戶端 - 請參閱您的客戶端技術文檔。

服務器 - 坐落在應對預檢(HTTP OPTIONS)調用的頭Access-Control-Allow-Credentialstrue(串)。

相關問題