2015-05-26 8 views
4

Я запускаю Rails 4.2, Devise 3.4.1 и CanCan 1.6.10. Когда я пытаюсь удалить ресурсы с помощью стандартной кнопки удаления, как показано ниже, я получаю подписку и перенаправляется на страницу входа.Rails 4 кнопка удаления выводит меня из системы и приводит к «Невозможно подтвердить подлинность CSRF-токена»

<a data-confirm="Are you sure?" class="btn-alert" rel="nofollow" data-method="delete" href="/admin/lots/6">Delete</a>

Мой журнал DEV говорит мне, что это потому, что «не удается проверить подлинность CSRF токен». Единственный способ, с помощью которого я могу заставить это работать, - это перейти от кнопки удаления к форме, которая отправляется в действие удаления, но это немного глупо. Я сделал это в других приложениях Rails 4, поэтому я уверен, что делаю это правильно.

index.html.erb

<% if can? :destroy, lot %> 
    <%= link_to "Delete", admin_lot_path(lot.id), method: :delete, data: {confirm: "Are you sure?"}, class: 'btn-alert' %> 
<% end %> 

lots_controller.rb

class Admin::LotsController < ApplicationController 
    before_filter :authenticate_user! 
    load_and_authorize_resource 

    def destroy 
    @lot.destroy 
    redirect_to admin_lots_path, notice: "Lot was successfully removed." 
    end 
end` 

Как я уже сказал, заменив кнопку с формой, кажется, работает, но это не является идеальным.

<%= form_for([:admin, lot], method: :delete) do |f| %> 
    <%= f.submit value: "Delete", class: 'btn-standard', data: {confirm: "Are you sure?"} %> 
<% end %> 

Если я закомментировать before_filter :authenticate_user! и load_and_authorize_resource от контроллера он работает. Я предполагаю, что токен csrf не отправляется вместе с этим запросом, как если бы он был в форме.

Есть ли у кого-нибудь идеи о том, что я могу попробовать? Желая опубликовать больше кода, если это будет полезно. Это происходит во всех удалениях в моем приложении.

Update: Вот отрывок из development.log

Started DELETE "/admin/lots/6" for 127.0.0.1 at 2015-05-26 15:03:22 -0500 
Processing by Admin::LotsController#destroy as HTML 
    Parameters: {"id"=>"6"} 
Can't verify CSRF token authenticity 
+0

Возможно, вам не хватает правильной поддержки JavaScript для Rails UJS. Уверены ли вы правильно загружены 'application.js'? – tadman

+0

Да, у меня '// = требуется jquery_ujs' там –

+0

Любые необычные ошибки JavaScript? Ваш запрос POST выглядит хорошо, например, он содержит токен CSRF? Здесь помогает сетевой инспектор. – tadman

ответ

5

Использование button_to вместо link_to.

button_to "Delete", admin_lot_path(lot.id), method: :delete, data: {confirm: "Are you sure?"}, class: 'btn-alert' 

link_to производит этот HTML, который отсутствует маркер подлинности,

<a data-confirm="Are you sure?" class="btn-alert" rel="nofollow" data-method="delete" href="/admin/lots/6">Delete</a> 

в то время как button_to производит

<form class="button_to" method="post" action="/admin/lots/6"> 
    <input type="hidden" name="_method" value="delete"> 
    <input data-confirm="Are you sure?" class="btn-alert" type="submit" value="Delete"> 
    <input type="hidden" name="authenticity_token" value="1QajBKKUzoEtUqi6ZX8DsQtT9BfvKY/WVXAr4lu4qb+iLGMkLlsviNcctlGxyq+VrsMa+U9vmb4PAdaRFDKZVQ=="> 
</form> 
+0

Я возьму это. Он по-прежнему создает форму, но, по крайней мере, это один лайнер. Я все еще смущен, почему link_to не работает. Я понимаю, что он не предоставляет токен csrf, но я делал это в прошлом. Может быть, он работал в Rails 3, а не Rails 4? –

+2

Ryan, у вас есть '= csrf_meta_tags' в тэге' head'? _ (edit: Я понял, что вы действительно ссылались на него выше. Я уверен, что это все еще требуется в Rails 4 для jQuery UJS для отправки токена аутентификации при запросах, не связанных с GET.) _ – Zek

+0

Sigh. После того, как все это работало с решением button_to, я увидел ваш ответ и подумал, что попробую добавить 'csrf_meta_tags' в голову и, конечно же, он работает сейчас. Спасибо за то, что вы меня дважды проверяли, я предпочитаю это решение. –

1

Вы должны передать маркер CSRF в качестве параметра, пример:

link_to "Delete", admin_lot_path(id: lot.id, authenticity_token: form_authenticity_token), method: :delete, data: {confirm: "Are you sure?"}, class: 'btn-alert' 

"form_authenticity_token" - это метод конвенции, который возвращает токен CSRF. Это подтвердит подлинность запроса.

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