2013-11-07 2 views
3

У меня есть файл PDF, который я не хочу публично открывать из URL-адреса на моем сайте. Как (легкий) уровень безопасности, я бы хотел отправить пользователям уникальный, случайно сгенерированный URL-адрес, из которого они могут загрузить PDF-файл, который я буду хранить на AWS или что-то подобное.Как я могу случайно создать ссылку на файл?

Я чувствую, что попал в тюрьму routes.rb, и я понятия не имею, как динамически создавать URL-адреса, а также как правильно создавать случайные URL-адреса, отслеживать их или связывать их с файлами, хранящимися локально или на AWS.

Есть ли у кого-нибудь предложения по решению этой проблемы?

ответ

3

Ах, да, я сделал это раньше. Я предполагаю, что вы будете использовать драгоценный камень загрузки файлов, такой как Paperclip и создал некоторые модели, такие как Pdf как:

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

Это создает модель, так что вы можете загрузить файл на него, и он будет хранить это в AWS S3. Возможно, у вас может не быть этого в настоящее время, но идея состоит в том, чтобы иметь запись базы данных, где вы можете иметь ссылку на URL-адрес Pdf, а также уникальный токен, который ваши пользователи будут использовать для извлечения, не зная реального URL.

В модели Pdf вы должны иметь маркер: строковое поле и в before_save фильтра в модели генерировать уникальный маркер:

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, и когда они пойдут к нему, ваше приложение найдет запись в базе данных этим токеном, вытащит реальный URL-адрес PDF на AWS, прочитать данные из него и принудительно загрузить в браузер все, не указав реального URL-адреса конечного пользователя.

2

Существует множество способов решения этой проблемы. Вероятно, самым простым является создание модели с поддержкой базы данных, в которой хранится ссылка на pdf и случайный идентификатор. Тогда действие show будет ссылкой в ​​формате /obscured_pdf/asdkfjlkdafj1230-5324.pdf или любым другим случайным идентификатором, с которым вы сталкиваетесь. Таким образом, для базового примера:

контроллер

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_id и pdf_id, так что вам не нужно его хранить вообще.

5

Как вы храните PDF?Если вы используете что-то вроде Paperclip, вы можете создать временный общественный URL в частный файл довольно легко:

class Attachment < ActiveRecord::Base 

    has_attached_file :file 

    # ... 

    def file_url 
    file.expiring_url(10) 
    end 

end 

file_url будет генерировать 10-вторых недействительный URL для этого файла. Затем, в любом контроллер имеет отношения, вы можете просто иметь «шоу» метод для самого файла, который быстро перенаправляет к частному 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 
Смежные вопросы