【问题标题】:Rails 6 - Allow/Disallow file download as per user role for files on AWS S3Rails 6 - 根据用户角色允许/禁止文件下载 AWS S3 上的文件
【发布时间】:2021-12-31 15:50:11
【问题描述】:

我有一个 Rails 6 应用程序,注册用户(所有者)可以在 S3 上上传文件 - 图像/视频,然后是 所有者 可以向其他用户提供访问权限(邀请)以查看他们上传的内容。

有没有办法可以限制文件访问,以便只有所有者才能下载他上传的文件(图像/视频),从而对其他非所有者/受邀用户实施限制。视频/图像不应通过右键单击并保存/下载它们来轻松下载。

注意 - 上传的文件还包括大视频(mp4 和 HLS 流媒体),因此其他受邀用户可以查看它们但不能下载,除非他们是所有者/uploaders,因为文件来自 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 并将其设为只读?
  • 将所有上传的文件设为公开并禁止非所有者公开访问,但这也会限制对文件的任何直接访问。

让我知道最适合这种方法的逻辑是什么。

【问题讨论】:

  • 为了让他们看到图像,浏览器会下载它——一旦他们看到它,就没有什么能阻止他们下载它。您最好的选择是在客户端限制它 - 或者您是否想要阻止下载,除非他们通过您的网络应用程序查看它?

标签: ruby-on-rails amazon-web-services amazon-s3 aws-sdk-ruby


【解决方案1】:

您要实现的目标需要多层次的基础:

  1. 基于S3 security best practices,您应该在 S3 端将权限级别保持在最低限度,以便应用提供预期的行为。

  2. S3 允许您to grant access to user specific folders

  3. 您应该查看the access granted gem 以涵盖服务器端限制。您还应该查看客户端限制。一种常见的技术是禁用鼠标右键。

相关:

How to download files without showing S3 URls

Top 7 security features for video streaming platforms

How Netflix protects its content

【讨论】:

  • 感谢 Azzen,感谢您的回答。然而,与我正在寻找的非常具体的内容相比,它非常通用,因为我不仅想使用 S3 权限,还想在 S3 上传的文件 - 用户 - 下载等操作之间创建动态。感谢您的宝贵时间。
【解决方案2】:

一个可能的选择是为您的 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>

【讨论】:

  • 这很好,但我可以对 CanCanCan 库进行相同的检查,如果它只是用于链接......但它不仅仅是应该控制下载的 Rails 应用程序,我也希望它是完全由 AWS S3 处理。
猜你喜欢
  • 2011-11-19
  • 2012-10-08
  • 2020-04-01
  • 2018-12-15
  • 2021-12-06
  • 1970-01-01
  • 1970-01-01
  • 2020-06-04
  • 2021-05-08
相关资源
最近更新 更多