2010-01-26 43 views
16

Tôi đang duy trì ứng dụng Rails có nội dung trong thư mục/công khai giờ đây cần được bảo vệ bằng thông tin đăng nhập. Chúng tôi đang xem xét việc di chuyển các thư mục đó của tệp vào một đường dẫn bên ngoài công cộng/và viết trình điều khiển Rails để phân phối nội dung.Bảo vệ nội dung công khai/trong ứng dụng Rails

Trước khi bắt đầu viết bài này, tôi đã tò mò liệu có ai khác đã gặp phải vấn đề này không? Tôi đã tìm một số đá quý/bổ sung mà có thể đã làm điều này nhưng không tìm thấy bất cứ điều gì. Có ai tạo ra một viên ngọc cho việc này không?

Trả lời

0

Nếu bạn muốn để buộc phân phối nội dung với xác thực Rails của bạn và hệ thống ủy quyền, sau đó bạn về cơ bản cần phải đặt nội dung đằng sau một bộ điều khiển.

Nếu bạn đang xem cách tiếp cận đăng nhập đơn giản hơn, bạn có thể xử lý nó bằng HTTP Auth và cài đặt trong môi trường lưu trữ của bạn (ví dụ: sử dụng htaccess).

16

Tôi đã thực hiện việc này trên trang web nơi mọi người trả tiền để tải xuống một số tệp nhất định và các tệp được lưu trữ trong RAILS_ROOT/private. Điều đầu tiên cần biết là bạn muốn máy chủ web xử lý việc gửi tệp, nếu không, ứng dụng của bạn sẽ được lưu trữ truyền tệp lớn và điều này sẽ nhanh chóng làm cho trang web của bạn bị tạm dừng nếu bạn có bất kỳ loại tải xuống nào. Vì vậy, nếu bạn cần phải kiểm tra ủy quyền trong một bộ điều khiển, sau đó bạn cũng cần một cách để vượt qua kiểm soát tải về trở lại máy chủ web. Cách tốt nhất để làm điều này (mà tôi biết) là tiêu đề X-Sendfile, được hỗ trợ bởi Nginx, Apache (với mô đun), và những thứ khác. Với X-Sendfile được cấu hình, khi máy chủ web của bạn nhận được tiêu đề từ ứng dụng của bạn, nó sẽ tiếp quản việc gửi tệp cho khách hàng.

Một khi bạn có X-Sendfile làm việc cho máy chủ web của bạn, một phương pháp điều khiển riêng như thế này rất hữu ích:

## 
# Send a protected file using the web server (via the x-sendfile header). 
# Takes the absolute file system path to the file and, optionally, a MIME type. 
# 
def send_file(filepath, options = {}) 
    options[:content_type] ||= "application/force-download" 
    response.headers['Content-Type'] = options[:content_type] 
    response.headers['Content-Disposition'] = "attachment; filename=\"#{File.basename(filepath)}\"" 
    response.headers['X-Sendfile'] = filepath 
    response.headers['Content-length'] = File.size(filepath) 
    render :nothing => true 
end 

Sau đó hành động điều khiển của bạn có thể trông giống như thế này:

## 
# Private file download: check permission first. 
# 
def download 
    product = Product.find_by_filename!(params[:filename]) 
    if current_user.has_bought?(product) or current_user.is_superuser? 
    if File.exist?(path = product.filepath) 
     send_file path, :content_type => "application/pdf" 
    else 
     not_found 
    end 
    else 
    not_authorized 
    end 
end 

Rõ ràng phương thức ủy quyền của bạn sẽ thay đổi và bạn sẽ cần thay đổi tiêu đề nếu bạn đang cung cấp tệp không phải PDF hoặc bạn muốn tệp được xem trong trình duyệt (loại bỏ loại nội dung application/force-download).

+5

Tại sao điều này không sử dụng phương thức send_file được xây dựng? –

+3

Bởi vì tôi không biết về nó! Bất kỳ ai sử dụng kỹ thuật này nên loại bỏ định nghĩa phương thức 'send_file' bị tê liệt của tôi và thay vào đó gọi đường dẫn' send_file' của Rails,: type => "application/pdf",: x_sendfile => true'. Cảm ơn vì lưu ý, Ryan. –

+0

Tôi đã nhận xét thêm về 'X-Sendfile' tại: http://stackoverflow.com/a/26884350/895245 –

0

Làm cho tập tin có sẵn tại một URL không thể đoán trước là một đơn giản giải pháp hiện đang được sử dụng trong một số hệ thống sản xuất.

Ví dụ: GitLab.Những hình ảnh sau đây đã được tải lên một vấn đề của một kho lưu trữ tư nhân, https://gitlab.com/cirosantilli/test-private/issues/1, nhưng bạn vẫn có thể nhìn thấy nó:

Lưu ý unguessable 90574279de tiền tố tự động thêm vào URL.

Bitbucket (không phải đường ray) cũng sử dụng kỹ thuật này.

Các vấn đề liên quan