Использование гема разработки для аутентификации всех пользователей приложения. Я пытаюсь внедрить Active Storage.
Допустим, все пользователи должны пройти аутентификацию, как только они попадут в приложение:
class ApplicationController < ActionController::Base
before_action :authenticate_user!
...
end
Как защитить маршруты, созданные Active Storage?
Доступ к URL-адресу загруженного файла можно получить без предварительной аутентификации. Неаутентифицированный пользователь может получить URL-адрес файла, созданный Active Storage.
Удалось ли вам решить эту проблему?
К сожалению, пока что я придерживаюсь святыни. Я думаю, что он не подходит для всех проектов. Но я уверен, что они будут улучшаться, как и в будущих выпусках.





Это не полный ответ, а отправная точка:
Суть: вам нужно будет переопределить контроллер перенаправления.
документы для activestorage / app / controllers / active_storage / blobs_controller.rb говорят:
If you need to enforce access protection beyond the security-through-obscurity factor of the signed blob references, you'll need to implement your own authenticated redirection controller.
Также, если вы планируете использовать превью, документы для activestorage / app / models / active_storage / blob /sentable.rb скажет
Active Storage provides one [controller action for previews], but you may want to create your own (for example, if you need authentication).
Также вы можете найти соответствующую информацию в эта проблема с рельсами на github
Обновлять:
Вот минимальный пример, который «должен» работать для предотвращения несанкционированного доступа к перенаправлениям при использовании гема devise.
Каким образом будет защищен URL-адрес, на который будет перенаправлен пользователь, если он будет зарегистрирован, - это еще одна история, я думаю. По умолчанию срок их действия истекает через 5 минут, но можно установить более короткий период, например 10 секунд (если вы замените строку 6 в примере ниже на expires_in 10.seconds)
Создайте файл app/controllers/active_storage/blobs_controller.rb со следующим кодом:
class ActiveStorage::BlobsController < ActiveStorage::BaseController
before_action :authenticate_user!
include ActiveStorage::SetBlob
def show
expires_in ActiveStorage::Blob.service.url_expires_in
redirect_to @blob.service_url(disposition: params[:disposition])
end
end
Обратите внимание, что единственное, что изменилось из исходный код, - это добавление второй строки
before_action :authenticate_user!
Обновление 2:
Вот проблема, которую вы можете включить в ActiveStorage::RepresentationsController и ActiveStorage::BlobsController, чтобы включить аутентификацию devise для ActiveStorage.
См. Суть в https://gist.github.com/dommmel/4e41b204b97238e9aaf35939ae8e1666, также здесь:
# Rails controller concern to enable Devise authentication for ActiveStorage.
# Put it in +app/controllers/concerns/blob_authenticatable.rb+ and include it when overriding
# +ActiveStorage::BlobsController+ and +ActiveStorage::RepresentationsController+.
#
# Optional configuration:
#
# Set the model that includes devise's database_authenticatable.
# Defaults to Devise.default_scope which defaults to the first
# devise role declared in your routes (usually :user)
#
# blob_authenticatable resource: :admin
#
# To specify how to determine if the current_user is allowed to access the
# blob, override the can_access_blob? method
#
# Minimal example:
#
# class ActiveStorage::BlobsController < ActiveStorage::BaseController
# include ActiveStorage::SetBlob
# include AdminOrUserAuthenticatable
#
# def show
# expires_in ActiveStorage::Blob.service.url_expires_in
# redirect_to @blob.service_url(disposition: params[:disposition])
# end
# end
#
# Complete example:
#
# class ActiveStorage::RepresentationsController < ActiveStorage::BaseController
# include ActiveStorage::SetBlob
# include AdminOrUserAuthenticatable
#
# blob_authenticatable resource: :admin
#
# def show
# expires_in ActiveStorage::Blob.service.url_expires_in
# redirect_to @blob.representation(params[:variation_key]).processed.service_url(disposition: params[:disposition])
# end
#
# private
#
# def can_access_blob?(current_user)
# @blob.attachments.map(&:record).all? { |record| record.user == current_user }
# end
# end
module BlobAuthenticatable
extend ActiveSupport::Concern
included do
around_action :wrap_in_authentication
end
module ClassMethods
def auth_resource
@auth_resource || Devise.default_scope
end
private
def blob_authenticatable(resource:)
@auth_resource = resource
end
end
private
def wrap_in_authentication
is_signed_in_and_authorized = send("#{self.class.auth_resource}_signed_in?") \
& can_access_blob?(send("current_#{self.class.auth_resource}"))
if is_signed_in_and_authorized
yield
else
head :unauthorized
end
end
def can_access_blob?(_user)
true
end
end
Спасибо, что нашли время оставить отзыв. Я голосую за, но до сих пор не объясняется, как защитить AS. ссылки, которые вы упомянули, только что сказали, что «вам нужно реализовать свой собственный аутентифицированный контроллер перенаправления», я тоже верю, но все же мы (как пользователи) не знаем пути, чтобы понять это;) вот и вся проблема.
Я обновил ответ небольшим примером кода. Возможно, мне придется реализовать это в будущем (именно так я пришел к вопросу в первую очередь), и если / когда я это сделаю, я обязательно вернусь сюда и поделюсь полным решением.
Спасибо за обновление! Я понимаю, что если мы хотим защитить AS, нам нужно переопределить несколько его частей. Я пока приму ответ и подожду будущих обновлений;) Я также протестирую его позже в существующем приложении, чтобы увидеть, как оно себя ведет.
Одна вещь, которую мы должны проверить, это то, что "незащищенные" старые маршруты / контроллер больше недоступны.
Это должно быть нормально, поскольку вы в основном используете тот же контроллер, что и раньше, но с добавленным before_action для обеспечения аутентификации. Имхо стоит упомянуть три вещи: 1) чтобы обезопасить превью / варианты файлов таким же образом, вы должны таким же образом переопределить app/controllers/active_storage/representations_controller.rb. 2) В приведенном выше примере не рассматривается проверка того, следует ли пользователю разрешить просмотр определенного файла. 3) Контроллер по-прежнему будет возвращать общедоступные URL-адреса (хотя и быстро истекающие). Я не думаю, что это проблема в большинстве случаев, просто нужно знать.
Если вы хотите реализовать аутентификацию для всех конечных точек, предоставляемых активным хранилищем, вы можете переопределить ActiveStorage::BaseController на основе оригинальная реализация:
# app/controllers/active_storage/base_controller.rb
# frozen_string_literal: true
# The base class for all Active Storage controllers.
class ActiveStorage::BaseController < ActionController::Base
before_action :authenticate_user!
include ActiveStorage::SetCurrent
protect_from_forgery with: :exception
end
Спасибо, работает! Я только что добавил include Devise::Controllers::Helpers перед вызовом аутентификации.
Отличный вопрос, я даже не подумал об этом. Должен быть какой-то способ поместить URL-адреса ActiveStorage в devise_scope, я думаю ...