Я разрабатываю приложение 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. Исходный код проекта можно найти здесь.