如何随机生成文件链接?

我有一个PDF文件,我不想通过我网站上的URL公开访问。 作为(轻微)安全层,我想通过电子邮件向用户发送一个独特的,随机生成的URL,他们可以从中下载PDF,我将在AWS上存储或类似的东西。

我觉得我被困在routes.rb监狱,我不知道如何动态生成URL,也不知道如何正确创建随机URL,跟踪它们,或将它们链接到本地​​或AWS上存储的文件。

有没有人有任何建议来解决这个问题?

啊,是的,我以前做过这件事。 我假设你将使用像Paperclip这样的文件上传gem并创建一些像Pdf这样的模型:

class Pdf < ActiveRecord::Base has_attached_file :pdf, storage: :s3 end 

这会设置模型,以便您可以将文件上传到它,并将其存储在AWS S3中。 您目前可能没有这种方式,但想法是拥有一个数据库记录,您可以在其中引用Pdf的URL以及用户将在不知道真实URL的情况下检索它的唯一令牌。

在Pdf模型中,您应该有一个token:string字段,并在模型的before_savefilter中生成唯一标记:

 class Pdf < ActiveRecord::Base require 'securerandom' has_attached_file :pdf, storage: :s3 before_save :generate_unique_token private def generate_unique_token self.token ||= SecureRandom.hex end end 

现在您可以设置命名路线:

 get '/hidden_pdf/:token', to: 'pdfs#get_hidden' 

将get_hidden操作添加到Pdfs控制器:

 class PdfsController < ApplicationController def get_hidden pdf = Pdf.where(token: params[:token]).first if pdf # from the pdf model you have access to its real URL and you can send it directly data = open pdf.url send_data data.read, filename: pdf.pdf_file_name, type: "application/pdf", disposition: 'inline', stream: 'true', buffer_size: '4096' else # Not found logic here end end end 

现在您可以向用户发送一个URL,例如myapp.com/pdfs/random-string-here ,当他们转到它时,您的应用程序将通过该令牌在数据库中找到记录,在AWS上提取PDF的真实URL ,从中读取数据并强制下载到浏览器,而不向最终用户显示真实的URL。

你是如何存储PDF的? 如果您使用Paperclip之类的东西,则可以非常轻松地生成私有文件的临时公共URL:

 class Attachment < ActiveRecord::Base has_attached_file :file # ... def file_url file.expiring_url(10) end end 

file_url将为该文件生成10秒有效的URL。 然后,在任何相关的控制器中,您可以为文件本身设置一个“show”方法,该方法在访问时快速重定向到私有URL:

 class AttachmentsController < ApplicationController # GET /whatever/attachments/:id def show redirect_to Attachment.find(params[:id]).file_url end end 

要实现像您要发送的“随机”url,您需要额外的一步。 您可以使用类似SecureRandom.uuid东西生成长哈希,并将其作为参数传递,并使用像AttachmentProxy这样的简单模型。

就像是:

 class AttachmentProxy < ActiveRecord::Base has_one :attachment # has an attribute called 'key', indexed... end 

在你的控制器中:

 class AttachmentProxyController < ApplicationController def show proxy = AttachmentProxy.find_by_key(params[:key]) redirect_to proxy.attachment.file_url end end 

有很多不同的方法可以解决这个问题。 最简单的可能只是创建一个数据库支持的模型,该模型存储对pdf和随机id的引用。 然后show动作将是格式为/obscured_pdf/asdkfjlkdafj1230-5324.pdf的链接或您提出的任何随机ID。 所以对于一个基本的例子:

调节器

 class ObscuredPdfsController < ApplicationController def show @pdf = ObscuredPdf.find_by_obscured_id(params[:id]).pdf # render pdf, do whatever end end 

在routes.rb中

 resources :obscured_pdfs, only: :show 

模糊的课程

 class ObscuredPdf < ActiveRecord::Base belongs_to :pdf belongs_to :user attr_accessible :obscured_id end 

更好的是,将obscured_id字段添加到pdf类,但如果多个人需要不同的链接指向同一个pdf,这也不行。 就个人而言,我最喜欢的选择是基于user_idpdf_id对称加密'随机'id,这样你根本不需要存储它。