Rails 4: не могу проверить подлинность токена CSRF, но данные все еще вставляются в базу данных

Я применяю CSRF в Controller, добавив это:

  class ApplicationController < ActionController::Base
     protect_from_forgery
  end

и я делаю почтовый запрос к моему API, используя Почтальон. Забавный результат - я не могу проверить CSRF, но данные, которые я отправляю, все равно будут вставлены в БД.

Вот журнал сервера.

 Processing by Api::ListingsController
   Parameters: {"listing"=>{...}}
 Can't verify CSRF token authenticity
   (0.2ms)  BEGIN
 SQL (0.6ms)  INSERT INTO "listings" ...
   (0.4ms)  COMMIT
 Completed 201 Created in 54ms (Views: 0.2ms | ActiveRecord: 6.3ms)

Кажется, все в порядке, и данные в БД сейчас! Почему CSRF не работает?

Кто-нибудь может дать какие-нибудь объяснения?

2 ответа

Существует три поведения, которые может вызвать несовпадение токена csrf:

  • поднять исключение (:exception)
  • сбросить сеанс на новый, пустой сеанс (:reset_session)
  • использовать пустую сессию для запроса, но не сбрасывать ее полностью (:null_session)

Обоснование для последних 2 заключается в том, что целью CSRF-атаки обычно является злоупотребление тем фактом, что пользователь уже вошел в систему, и, следовательно, браузер будет отправлять сеансовые куки-файлы с запросом. Поэтому сброс или игнорирование сеанса (при условии, что именно там хранятся учетные данные) сделает запрос продолженным как неаутентифицированный запрос.

Если приложение не требует, чтобы пользователь вошел в систему, то :null_session а также :reset_session позволит запрос продолжить.

Поведение по умолчанию изменилось за эти годы, но по состоянию на рельсы 4.2 это :null_session, Вы можете изменить его, указав with возможность protect_from_forgery

В ApplicationController можете добавить

class ApplicationController < ActionController::Base
    protect_from_forgery with: :null_session, if: Proc.new { |c| c.request.format      == 'application/json' }
    # Or
    # skip_before_filter :verify_authenticity_token, :if => Proc.new { |c| c.request.format == 'application/json' }
end
Другие вопросы по тегам