Старый вопрос, но безопасность достаточно важна, и я считаю, что она заслуживает полного ответа. Как обсуждалось в этом вопросе , риск CSRF все еще существует, даже с API. Да, браузеры должны защищать от этого по умолчанию, но, поскольку у вас нет полного контроля над браузером и плагинами, которые установил пользователь, это все равно следует считать лучшей практикой защиты от CSRF в вашем API.
Иногда я видел, как это делается, - анализировать метатег CSRF с самой HTML-страницы. Мне это не очень нравится, поскольку оно не очень хорошо сочетается с тем, как сегодня работает множество одностраничных приложений + API, и я чувствую, что токен CSRF следует отправлять при каждом запросе независимо от того, является ли он HTML, JSON или XML.
Поэтому я бы предложил вместо этого передавать токен CSRF в виде значения cookie или заголовка через фильтр после для всех запросов. API может просто повторно передать это обратно в качестве значения заголовка X-CSRF-Token
, которое Rails уже проверяет.
Вот как я это сделал с AngularJS:
# In my ApplicationController
after_filter :set_csrf_cookie
def set_csrf_cookie
if protect_against_forgery?
cookies['XSRF-TOKEN'] = form_authenticity_token
end
end
AngularJS автоматически ищет файл cookie с именем XSRF-TOKEN
, но не стесняйтесь называть его как угодно для ваших целей. Затем, когда вы отправляете POST / PUT / DELETE, вы должны установить свойство заголовка X-CSRF-Token
, которое Rails автоматически ищет.
К сожалению, AngualrJS уже отправляет обратно cookie XSRF-TOKEN
со значением заголовка X-XSRF-TOKEN
. Повторить поведение Rails по умолчанию легко, чтобы приспособить это к ApplicationController
, например:
protected
def verified_request?
super || form_authenticity_token == request.headers['X-XSRF-TOKEN']
end
Для Rails 4.2 теперь есть встроенный помощник для проверки CSRF, который следует использовать.
protected
def verified_request?
super || valid_authenticity_token?(session, request.headers['X-XSRF-TOKEN'])
end
Надеюсь, это полезно.
РЕДАКТИРОВАТЬ: В обсуждении этого для pull-запроса Rails я представил, что получилось, что передача токена CSRF через API для входа в систему является особенно плохой практикой (например, кто-то может создать третий партийный логин для вашего сайта, который использует учетные данные пользователя вместо токенов). Так что будьте бдительны. Это зависит от вас, чтобы решить, насколько вы обеспокоены этим для вашего приложения. В этом случае вы все еще могли бы использовать описанный выше подход, но отправлять обратно файл cookie CSRF только в браузер, в котором уже есть аутентифицированный сеанс, и не для каждого запроса. Это предотвратит отправку действительного имени входа без использования метатега CSRF.