Rails, Rackspace Cloud Files, Referrer ACL
I am using Rackspace Cloud Files as File Storage server for my application. The files that users upload must be authorized from within my application, then from a controller it would redirect to the correct Rackspace Cloud Files CDN URL. I am trying to do authorization using Rackspace Cloud Files' Referrer ACL.
So let me just add a very simple snippet to clarify what I am trying to accomplish.
class FilesController < ApplicationController
def download
redirect_to(some_url_to_a_file_on_cloud_files_url)
end
end
The URL the user would access to get to this download action would be the following:
http://a-subdomain.domain.com/projects/:project_id/files/:file_id/download
So with the CloudFiles gem I have set up an ACL Referrer regular expression that should work.
http\:\/\/.+\.domain\.com\/projects\/\d+\/files\/\d+\/download
When the user clicks on a link in the web UI, it routes them to the above URL and depending on the parameters, it will from the download action redirect the user to the correct Rackspace Cloud Files File URL.
Well, what I get is an error, saying that I am unauthorized (wrong http referrer). I have a hunch that because I am doing a redirect from the download action straight to cloud files, that it doesn't "count" as a HTTP Referrer and, rather than use this URL as a referrer, I think it might be using this URL:
http\:\/\/.+\.domain\.com\/projects\/\d+\/files
Since this is the page you are on when you want to click on the "download" link, that directs the user to the download action in the FilesController.
When I set the HTTP Referrer for Rackspace ACL to just this:
http\:\/\/.+\.domain\.com\/projects\/\d+\/files
And then click on a link, I am authorized to download. However, this isn't safe enough since then anyone could for example just firebug into the html and inject a raw link to the file and gain access.
So I guess my question is, does anyone have any clue how or why, what I am trying to accomplish is not working, and have any suggestions/ideas? As I said I think it might be that when a user clicks the link, that the referrer is being set to the location of which the file is being clicked, not the url where the user is being redirected to the actual file on cloud files.
Is something lik开发者_JAVA百科e this possible?
class FilesController < ApplicationController
def download
# Dynamically set a HTTP Referrer here before
# redirecting the user to the actual file on cloud files
# so the user is authorized to download the file?
redirect_to(some_url_to_a_file_on_cloud_files_url)
end
end
Any help, suggestions are much appreciated!
Thanks!
Generally Micahel's comment is more than enough to explain why S3 tops rackspace for this matter, but if you'd really like to add some special HTTP headers to your Rackspace request - do an HTTP request of your own and fetch the file manually:
class DownloadsController < ApplicationController
def download
send_data HTTParty.get(some_url_to_a_file_on_cloud_files_url, :headers => {"x-special-headers" => "AWESOME" }), :file_name => "myfile.something"
end
end
Yes, you can code this example better but it's the general idea.
Although there is still no 'Referer' check, you can create temp urls (signed urls) with the current version of Rackspace CloudFiles.
The following code is taken from Rackspace documentation site.
require "openssl"
unless ARGV.length == 4
puts "Syntax: <method> <url> <seconds> <key>"
puts ("Example: GET https://storage101.dfw1.clouddrive.com/v1/" +
"MossoCloudFS_12345678-9abc-def0-1234-56789abcdef0/" +
"container/path/to/object.file 60 my_shared_secret_key")
else
method, url, seconds, key = ARGV
method = method.upcase
base_url, object_path = url.split(/\/v1\//)
object_path = '/v1/' + object_path
seconds = seconds.to_i
expires = (Time.now + seconds).to_i
hmac_body = "#{method}\n#{expires}\n#{object_path}"
sig = OpenSSL::HMAC.hexdigest("sha1", key, hmac_body)
puts ("#{base_url}#{object_path}?" +
"temp_url_sig=#{sig}&temp_url_expires=#{expires}")
end
精彩评论