Как убедиться, что Rails API защищен от CSRF?
Я разрабатываю приложение Rails с REST API для доступа из мобильного приложения.
Это работает очень хорошо. Когда пользователь входит в систему из мобильного приложения, он получает auth_token
, который он использует в своих будущих запросах API. Проблема в том, что API также доступен из Интернета, перейдя по пути /api/v 1/... и из-за этого он должен быть защищен от CSRF.
У меня есть класс BaseApiController
, который наследует от ApplicationController
, который имеет protect_from_forgery
"enabled". Вот пример:
class Api::V1::BaseApiController < ApplicationController
# ...
end
class ApplicationController < ActionController::Base
protect_from_forgery
# ...
end
Теперь, когда я выполняю не-GET-запросы к моему API, с auth_token
мой запрос будет успешно завершен, но в журналах я могу увидеть знаменитый WARNING: Can't verify CSRF token authenticity
. Если я удалю protect_from_forgery
из моего BaseApiController
, я не получаю никаких предупреждений (очевидно), но тогда мой API уязвим для атак CSRF (я создал простую форму HTML, которая успешно изменяет данные по доменам, когда нет protect_from_forgery
).
Мой вопрос: как обеспечить, чтобы мой API оставался безопасным, но также удалял предупреждение при выполнении запросов, отличных от GET?
Здесь один из решений, которые я придумал, но он больше похож на взломанный и выполняет один дополнительный запрос БД:
class Api::V1::BaseApiController < ApplicationController
# ...
def verified_request?
super || User.where(authentication_token: params['auth_token']).count > 0
end
end
Подробнее о проекте: Rails 3.2.14, Devise, AngularJS. Исходный код проекта можно найти здесь.
Ответы
Ответ 1
Вы можете видеть, что люди предполагают, что CSRF не является проблемой для запросов API (с самого начала не существует какого-либо состояния, так что же все-таки уклониться?), поэтому некоторые предлагают следующее, чтобы просто устранить предупреждение:
skip_before_filter :verify_authenticity_token, :only => [:your_method]
Однако был комментарий, что можно зафиксировать CSRF с помощью text/plain
, используя различные методы на основе Flash и Java. Я считаю, что это было причиной исправления безопасности в рельсах некоторое время назад: http://weblog.rubyonrails.org/2011/2/8/csrf-protection-bypass-in-ruby-on-rails/
В любом случае хорошее решение, которое действительно проверяет токен аутентификации, можно найти здесь: ПРЕДУПРЕЖДЕНИЕ: Невозможно проверить рельсы аутентификации маркера CSRF
Он включает в себя собственно настройку заголовка в вашем запросе.
Удачи!