2016-11-14 3 views
1

Я научился использовать феникс-фреймворк, и я пытаюсь сделать пост AJAX для действия контроллера, однако я столкнулся с проблемой защиты CSRF.Phoenix - invald CSRF на пост AJAX

Для начала, я не использую форму - просто хочу, чтобы передать текст от входа к контроллеру:

<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 

Я довольно сильно поднял вызов $.ajax из приложения Rails, где он работал нормально, но это не делает трюк здесь - запуск этого возвращает ошибку 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

У вас есть метатег CSRF в вашем html? – Gazler

+0

Спасибо @Gazler - Я также смог разрешить это, добавив метатег, как вы предлагаете. То, чего мне не хватало при тестировании ранее, было то, что Phoenix ожидает параметр как '_csrf_token', который вы даже можете увидеть в моем вопросе выше. Просто пропустил эту мелочь ... хорошо, живи и учись! – skwidbreth

ответ

6

Это потому, что по умолчанию Феникс не создает метатег с маркером CSRF. Они включаются только в формы, созданные вспомогательными функциями Phoenix, и они скрыты.

Чтобы получить программный токен CSRF в Phoenix, вы можете позвонить 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

Спасибо, это здорово - просто FYI, когда я использовал ваш код, я получил ошибку 'Uncaught SyntaxError: Неожиданный токен &' ссылающийся на 'var CSRF_TOKEN = " NXQ8YzQGLS0KPgskMTAXAAQeHVgaJgAAB8XZngDckuEVdiF2VPV1sw == ";'. Возвращаясь к моему опыту Rails, я вспомнил, что вы можете использовать 'raw', чтобы обойти это, поэтому итоговой рабочей версией является' var CSRF_TOKEN = <% = raw Poison.encode! (Plug.CSRFProtection.get_csrf_token())%> ; ' – skwidbreth

+1

Вы правы, @skwidbreth. Я исправил свой ответ. – Dogbert

+0

хорошее командное усилие! – skwidbreth

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