开发者

Rails, Rackspace Cloud Files, Referrer ACL

开发者 https://www.devze.com 2023-01-21 18:37 出处:网络
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 c

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
0

精彩评论

暂无评论...
验证码 换一张
取 消