一个可能的选择是为您的 s3 对象生成签名的 url,并在您的 rails 应用程序中具有“授权”逻辑。这应该是 ActiveStorage 的默认设置,否则如果您使用 Carrierwave,则需要设置 fog_public = false
选项1:
在显示下载文件按钮的视图中:
- if user.can_access_document?(document)
= link_to 'View', document.attachment_url, target: :blank
- else
Request an invite from the owner
在您的用户模型中:
class User < ApplicationRecord
has_many :invitations
...
def can_access_document?(document)
# Check if there is an invitation entry for this user to access said file
self.invitations.where(document_id: document.id).any?
end
end
选项 2
您还可以让按钮点击特定端点/路由到您的一个控制器,例如Files#download_file
,然后在那里进行签入并重定向到 s3 文件。
class FilesController < ApplicationController
def download
document = Document.find(params[:id])
if current_user.can_access_document?(document)
redirect_to document_url
else
raise "You don't have access to this document"
end
end
end
在您看来,只需将链接指向您的新控制器
= link_to 'View', download_files_url(document), target: :blank
由于文件的 url 已签名,用户将需要单击您网站上的按钮,并且不能一遍又一遍地使用相同的 url。这些签名的 url 也可以有一个动态的过期时间,例如,如果链接设置为 60 秒后过期,如果用户在 60 秒后点击下载文件,他/她将显示一个 s3 错误,说明链接已过期,如下所示:
<Error>
<Code>AccessDenied</Code>
<Message>Request has expired</Message>
<Expires>2018-06-28T07:13:14Z</Expires>
<ServerTime>2018-08-06T20:03:02Z</ServerTime>
<RequestId>87E1D2CFAAA7F9A6</RequestId>
<HostId>
A9BEluTV2hk3ltdFkixvQFa/yUBfUSgDjptwphKze+jXR6tYbpHCx8Z7y6WTfxu3rS4cGk5/WTQ=
</HostId>
</Error>