Защитите активное хранилище с помощью devise

Использование гема разработки для аутентификации всех пользователей приложения. Я пытаюсь внедрить Active Storage.

Допустим, все пользователи должны пройти аутентификацию, как только они попадут в приложение:

class ApplicationController < ActionController::Base
  before_action :authenticate_user!

...
end

Как защитить маршруты, созданные Active Storage?

Доступ к URL-адресу загруженного файла можно получить без предварительной аутентификации. Неаутентифицированный пользователь может получить URL-адрес файла, созданный Active Storage.

Отличный вопрос, я даже не подумал об этом. Должен быть какой-то способ поместить URL-адреса ActiveStorage в devise_scope, я думаю ...

emptywalls 13.04.2018 23:59

Удалось ли вам решить эту проблему?

Rcordoval 24.04.2018 22:42

К сожалению, пока что я придерживаюсь святыни. Я думаю, что он не подходит для всех проектов. Но я уверен, что они будут улучшаться, как и в будущих выпусках.

coding addicted 25.04.2018 00:16
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
15
3
4 293
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Это не полный ответ, а отправная точка:

Суть: вам нужно будет переопределить контроллер перенаправления.

документы для 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. ссылки, которые вы упомянули, только что сказали, что «вам нужно реализовать свой собственный аутентифицированный контроллер перенаправления», я тоже верю, но все же мы (как пользователи) не знаем пути, чтобы понять это;) вот и вся проблема.

coding addicted 01.05.2018 22:43

Я обновил ответ небольшим примером кода. Возможно, мне придется реализовать это в будущем (именно так я пришел к вопросу в первую очередь), и если / когда я это сделаю, я обязательно вернусь сюда и поделюсь полным решением.

Domi 02.05.2018 14:14

Спасибо за обновление! Я понимаю, что если мы хотим защитить AS, нам нужно переопределить несколько его частей. Я пока приму ответ и подожду будущих обновлений;) Я также протестирую его позже в существующем приложении, чтобы увидеть, как оно себя ведет.

coding addicted 02.05.2018 18:24

Одна вещь, которую мы должны проверить, это то, что "незащищенные" старые маршруты / контроллер больше недоступны.

coding addicted 02.05.2018 18:27

Это должно быть нормально, поскольку вы в основном используете тот же контроллер, что и раньше, но с добавленным before_action для обеспечения аутентификации. Имхо стоит упомянуть три вещи: 1) чтобы обезопасить превью / варианты файлов таким же образом, вы должны таким же образом переопределить app/controllers/active_storage/representations_controller.rb. 2) В приведенном выше примере не рассматривается проверка того, следует ли пользователю разрешить просмотр определенного файла. 3) Контроллер по-прежнему будет возвращать общедоступные URL-адреса (хотя и быстро истекающие). Я не думаю, что это проблема в большинстве случаев, просто нужно знать.

Domi 02.05.2018 20:57

Если вы хотите реализовать аутентификацию для всех конечных точек, предоставляемых активным хранилищем, вы можете переопределить 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 перед вызовом аутентификации.

Sasha B. 10.05.2021 21:28

Другие вопросы по теме