Scenario: Grant access to some assets only to premium users
How do we go about doing this in an efficient way?
Prevent direct access to your assets
If you're using NginX, the following configuration would handle this part:
location /secured_assets {
internal;
}
So if you have a file named top-secret.pdf in public/secured_assets/top-secret.pdf, then trying to access it directly would result in a 404 not found error.
Create an entry point to your asset
The most obvious way of going about this is to create a route to some controller where you would do the authorization and determine whether the current user trying to retrieve the resource is indeed allowed to access it. Best explained by code.
# in your routes
map.secured_asset '/secured/asset/*slug', :controller => 'secured/assets', :action => 'show'
# in your controller
def show
if authorized? # of course do your crazy business logic here
headers['X-Accel-Redirect'] = File.join("secured_assets", *params[:slug])
render :nothing => true
else
render :nothing => true, :status => 403
end
end
The headers part makes sure that nginx is the one responsible for actually streaming the file, freeing your rails application from delivering it.