我有托管在Heroku Rails应用程序。 该应用程序生成并存储在Amazon S3上的PDF文件。 用户可以下载这些文件用于查看自己的浏览器或保存在电脑上。
我遇到的问题是,虽然这些文件的下载通过S3 URL是可能的(如“https://s3.amazonaws.com/my-bucket/F4D8CESSDF.pdf”),这显然是不该做的好方法它。 这是不希望暴露给用户这么多的信息有关的后端,更不用说上升的安全问题。
是否有可能有我的应用程序以某种方式检索S3文件数据在控制器,然后为用户创建了一个下载流,从而使亚马逊URL不会暴露?
是的,这是可能的 - 只是取得与Rails的远程文件,要么临时存储它的服务器上或直接由缓冲区发送。 这个问题当然是,你需要先获取该文件之前,您可以在服务于用户的事实。 见这个线程的讨论,他们的解决方案是这样的:
#environment.rb
require 'open-uri'
#controller
def index
data = open(params[:file])
send_data data, :filename => params[:name], ...
end
这个问题也有点关系 。
您可以创建S3对象为私有,并为他们临时公共网址url_for方法(AWS-S3宝石)。 这样,你不通过你的应用服务器,这是更具扩展性的流文件。 它还允许将基于会话的授权(例如,在设计你的应用程序),下载事件等的跟踪
为了做到这一点,改变直接链接到托管文件s3的链接进入到控制器/它创建临时URL和重定向到它的行动。 像这样:
class HostedFilesController < ApplicationController
def show
s3_name = params[:id] # sanitize name here, restrict access to only some paths, etc
AWS::S3::Base.establish_connection!( ... )
url = AWS::S3::S3Object.url_for(s3_name, YOUR_BUCKET, :expires_in => 2.minutes)
redirect_to url
end
end
亚马逊域的下载网址隐藏通常与DNS别名来完成。 您需要创建CNAME记录别名子域名 ,如downloads.mydomain
,以s3.amazonaws.com
。 然后,你可以指定:server
在选择AWS::S3::Base.establish_connection!(:server => "downloads.mydomain", ...)
和S3创业板将用它来生成链接。
首先,你需要在你的域创建CNAME,如解释在这里 。
其次,你需要创建与你把CNAME同名的水桶。
并完成你需要在你的配置/初始化/ carrierwave.rb添加此配置:
CarrierWave.configure do |config|
...
config.asset_host = 'http://bucket_name.your_domain.com'
config.fog_directory = 'bucket_name.your_domain.com'
...
end
文章来源: Rails: allow download of files stored on S3 without showing the actual S3 URL to user