[英]Secure active storage with devise
使用 devise gem 對應用程序的所有用戶進行身份驗證。 我正在嘗試實施 Active Storage。
假設所有用戶在訪問應用程序時都必須進行身份驗證:
class ApplicationController < ActionController::Base
before_action :authenticate_user!
...
end
如何保護 Active Storage 生成的路由?
無需先進行身份驗證即可訪問上傳文件的 URL。 未經身份驗證的用戶可以獲取 Active Storage 生成的文件 url。
這不是一個完整的答案,而是一個起點:
要點:您需要覆蓋重定向控制器。
activestorage/app/controllers/active_storage/blobs_controller.rb 的文檔說:
如果您需要在簽名 blob 引用的隱匿性安全因素之外強制執行訪問保護,則需要實現自己的經過身份驗證的重定向控制器。
此外,如果您打算使用預覽文檔 activestorage/app/models/active_storage/blob/representable.rb說
Active Storage 提供了一種 [用於預覽的控制器操作],但您可能希望創建自己的(例如,如果您需要身份驗證)。
你也可以在這個 rails github issue 中找到一些相關信息
更新:這是一個“應該”用於在使用devise
gem 時防止未經授權訪問重定向的最小示例。
如果登錄后用戶將被重定向到的 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
包含的一個問題,以啟用ActiveStorage
devise
身份驗證
見要點在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
如果要對主動存儲提供的所有端點實現身份驗證,可以在原始實現的基礎上覆蓋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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.