Подтвердить что ты не робот

Rails: не удается проверить подлинность CSRF-маркера при выполнении запроса POST

Я хочу сделать POST request для моего локального разработчика, например:

  HTTParty.post('http://localhost:3000/fetch_heroku',
                :body => {:type => 'product'},)

Однако с консоли сервера он сообщает

Started POST "/fetch_heroku" for 127.0.0.1 at 2016-02-03 23:33:39 +0800
  ActiveRecord::SchemaMigration Load (0.0ms)  SELECT "schema_migrations".* FROM "schema_migrations"
Processing by AdminController#fetch_heroku as */*
  Parameters: {"type"=>"product"}
Can't verify CSRF token authenticity
Completed 422 Unprocessable Entity in 1ms

Вот мой контроллер и настройка маршрутов, это довольно просто.

  def fetch_heroku
    if params[:type] == 'product'
      flash[:alert] = 'Fetch Product From Heroku'
      Heroku.get_product
    end
  end

  post 'fetch_heroku' => 'admin#fetch_heroku'

Я не уверен, что мне нужно делать? Отключение CSRF, безусловно, будет работать, но я думаю, что это должна быть моя ошибка при создании такого API.

Есть ли какая-нибудь другая настройка, которую мне нужно сделать?

4b9b3361

Ответ 1

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

Rails CSRF-защита предназначена для "классических" веб-приложений - она просто дает определенную степень уверенности в том, что запрос возник из вашего собственного веб-приложения. Токен CSRF работает как секрет, который знает только ваш сервер - Rails генерирует случайный токен и сохраняет его в сеансе. Ваши формы отправляют токен через скрытый ввод, и Rails проверяет, что любой не GET-запрос включает токен, который соответствует тому, что хранится в сеансе.

Однако API по определению обычно является межсайтовым и предназначен для использования не только в вашем веб-приложении, что означает, что концепция CSRF не совсем применима.

Вместо этого вам следует использовать основанную на токене стратегию аутентификации запросов API с ключом и секретом API, поскольку вы проверяете, что запрос поступает от утвержденного клиента API, а не от вашего собственного приложения.

Вы можете деактивировать CSRF, как указано @dcestari:

class ApiController < ActionController::Base
  protect_from_forgery with: :null_session
end

Обновлено. В Rails 5 вы можете создавать приложения только API, используя опцию --api:

rails new appname --api

Они не включают промежуточное программное обеспечение CSRF и многие другие компоненты, которые являются суперфлюусами.

Ответ 2

Еще один способ отключить функцию CSRF, которая не будет отображать нулевой сеанс, - добавить:

skip_before_action :verify_authenticity_token

в вашем Rails Controller. Это обеспечит вам доступ к информации о сеансе.

Опять же, убедитесь, что вы делаете это только на контроллерах API или в других местах, где защита CSRF не совсем применима.

Ответ 3

Существует соответствующая информация о конфигурации CSRF в отношении контроллеров API на api.rubyonrails.org:

Важно помнить, что запросы XML или JSON также затронуты, и если вы создаете API, вы должны изменить метод защиты подделок в ApplicationController (по умолчанию :exception):

class ApplicationController < ActionController::Base
  protect_from_forgery unless: -> { request.format.json? }
end

Мы можем отключить защиту CSRF для API, поскольку они, как правило, предназначены для бездействия. То есть клиент API запроса будет обрабатывать сеанс для вас вместо Rails.

Ответ 4

В Rails 5 вы также можете создать новый класс с :: API вместо :: Base:

class ApiController < ActionController::API
end

Ответ 5

Если вы хотите исключить образец действия образца контроллера

class TestController < ApplicationController
  protect_from_forgery :except => [:sample]

  def sample
     render json: @hogehoge
  end
end

Вы можете обрабатывать запросы извне без проблем.