Как убедиться, что 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

Он включает в себя собственно настройку заголовка в вашем запросе.

Удачи!