Rails 6 - 允许/禁止根据用户角色从AWS S3中下载文件

5
我有一个Rails 6应用程序,其中已注册用户(所有者)可以在S3上上传文件(图像/视频),然后所有者可以向其他用户(邀请)提供访问权限以查看其上传的内容。 是否有一种方法可以限制文件访问,以便只有所有者可以下载他上传的文件(图像/视频),从而对非所有者/被邀请者设置限制。 不能通过右键单击和轻松保存/下载视频/图像。 注意 - 上传的文件还包括大型视频(包括mp4和HLS流),因此其他被邀请的用户可以查看它们,但除了所有者/上传者外,无法下载它们,因为视频来自AWS Cloudfront,而图像来自S3。
关联设置如下 -
User has one role
User has many images/videos, each residing in his own folder on s3(`bucket/user_id/image_slug/` or `bucket/user_id/video_slug/`)
User has many invitations(must be view only access to owners file)

不确定采取正确的方法,可能是 -

  • 如果非所有者访问文件,则更新文件的ACL并使其只读?
  • 将所有上传的文件设为公共文件,并禁用非所有者的公共访问权限,但这也会限制任何对文件的直接访问。

请告诉我哪种逻辑最适合此方法。


为了让他们看到图片,浏览器会下载它 - 一旦他们看到了它,就没有什么可以阻止他们下载它了。你最好在客户端限制它 - 或者你想要防止下载,除非他们通过你的 Web 应用程序查看它? - Ermiya Eskandary
2个回答

2
您需要在多个层面上打下基础来实现您想要的目标:
  1. 根据S3安全最佳实践,您应该将S3端的权限级别最小化到足以提供所需行为的水平。

  2. S3允许您授予用户特定文件夹的访问权限

  3. 您应该使用access granted gem来覆盖服务器端限制。 您还应该研究客户端限制。 一种常见的技术是禁用鼠标右键单击功能。

相关:

如何下载文件而不显示S3 URL

视频流媒体平台的7个安全功能

Netflix如何保护其内容


谢谢Azzen,谢谢你的回答。然而相比我正在寻找的非常具体的内容,它还是有点泛泛而谈。我想使用的不仅仅是S3权限,还要在S3上传的文件、用户和动作(例如下载)之间创建动态联系。感谢你的时间。 - Milind

1
一个可能的选择是生成带签名的url到你的s3对象,然后在你的rails应用程序中处理“authorization”逻辑。如果您使用的是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>

这很好,但如果只是针对链接,我可以使用CanCanCan库进行相同的检查...但不仅仅是Rails应用程序应该管理下载,我还希望AWS S3完全负责处理它。 - Milind

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接