2016-11-14 100 views
1

我正在學習使用鳳凰框架,我試圖做一個控制器動作的AJAX後 - 但是,我遇到了CSRF保護問題。鳳凰城 - 在AJAX postFlow CSRF後

對於初學者來說,我使用的不是一個形式 - 只是想從一個輸入文字傳遞給控制器​​:

<input type="text" id="raw-input" /> 
<button id="send-button">Send it!</button> 

<script> 
$("#send-button").click(function(){ 
    var input = $("#raw-input").val(); 

    $.ajax({ 
     url: "/test/process", 
     type: "POST", 
     dataType: "json", 
     beforeSend: function(xhr) {xhr.setRequestHeader("X-CSRF-Token", $("meta[name='csrf-token']").attr("content"))}, 
     data: {"input" : input}, 
     success: function(response){ 
      console.log(response); 
     } 
    }); 
}); 
</script> 

控制器(不擔心做什麼input尚未...只是想驗證成功後):

def process(conn, %{"input" => input}) do 
    IO.puts "got it!" 
end 

和路由器:

post "/test/process", TestController, :process 

我幾乎從一個Rails應用程序的$.ajax調用中取得了很好的效果,但這裏並沒有這樣做 - 運行這個會返回一個403錯誤並記錄(Plug.CSRFProtection.InvalidCSRFTokenError) invalid CSRF (Cross Site Request Forgery) token, make sure all requests include a valid '_csrf_token' param or 'x-csrf-token' header

任何人都可以提供任何指導?謝謝!

+1

你在你的html中有CSRF元標記嗎? – Gazler

+0

謝謝@Gazler - 我也可以通過添加meta標籤來解決這個問題。我之前測試時缺少的東西是Phoenix期望參數爲'_csrf_token',在上面的問題中您甚至可以看到這個參數。只是錯過了那個小細節...好吧,現場學習! – skwidbreth

回答

6

這是因爲Phoenix默認情況下不會創建帶有CSRF標記的元標記。它們只包含在由Phoenix的幫助函數生成的表單中,並且它們隱藏在輸入中。

要在Phoenix中以編程方式獲得CSRF令牌,您可以撥打Plug.CSRFProtection.get_csrf_token/0。有很多方法可以將它傳遞給你的JS。您可以將元標記添加到佈局以將其包含在每個頁面中,但這可能不是非常有效,因爲它會針對所有頁面生成。你也可以將它存儲在你需要它們的視圖中的JS變量中:

<input type="text" id="raw-input" /> 
<button id="send-button">Send it!</button> 

<script> 
$("#send-button").click(function(){ 
    var CSRF_TOKEN = <%= raw Poison.encode!(Plug.CSRFProtection.get_csrf_token()) %>; 
    var input = $("#raw-input").val(); 

    $.ajax({ 
     url: "/test/process", 
     type: "POST", 
     dataType: "json", 
     beforeSend: function(xhr) { 
      xhr.setRequestHeader("X-CSRF-Token", CSRF_TOKEN); 
     }, 
     data: {"input" : input}, 
     success: function(response){ 
      console.log(response); 
     } 
    }); 
}); 
</script> 
+0

謝謝,這真是太棒了 - 僅供參考,當我使用您的代碼時,出現錯誤'未捕獲的SyntaxError:意外的令牌&'參考'var CSRF_TOKEN = " NXQ8YzQGLS0KPgskMTAXAAQeHVgaJgAAB8XZngDckuEVdiF2VPV1sw == ";'。回想我的Rails經驗,我記得你可以使用'raw'來解決這個問題 - 所以最終的工作版本是'var CSRF_TOKEN = <%= raw Poison.encode!(Plug.CSRFProtection.get_csrf_token())%> ;' – skwidbreth

+1

你說得對,@skwidbreth。我已經解決了我的答案。 – Dogbert

+0

不錯的團隊精神! – skwidbreth