Ответ 1
Старый вопрос, но безопасность важна настолько, что я считаю, что он заслуживает полного ответа. Как обсуждалось в этом question, по-прежнему существует некоторый риск 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 уже отправляет файл XSRF-TOKEN
cookie в значение заголовка 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
Надеюсь, что это полезно.
EDIT: в обсуждение этого вопроса для запроса запроса Rails. Я представил, что передача токена CSRF через API для логин - особенно плохая практика (например, кто-то может создать сторонний логин для вашего сайта, который использует учетные данные пользователя вместо токенов). Итак, кабальный эмиттер. Вам решать, насколько вы обеспокоены тем, что касается вашего приложения. В этом случае вы все равно можете использовать вышеупомянутый подход, но только отсылаете CSRF файл cookie в браузер, который уже имеет аутентифицированный сеанс, а не для каждого запроса. Это предотвратит отправку действительного входа без использования метатега CSRF.