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.
Есть ли какая-нибудь другая настройка, которую мне нужно сделать?
Ответы
Ответ 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
Вы можете обрабатывать запросы извне без проблем.