I've been doing some research regarding file downloads with access control, using Django. My goal is to completely block access to a file, except when accessed by a specific user. I've read that when using Django, X-Sendfile is one of the methods of choice for achieving this (based on other SO questions, etc). My rudimentary understanding of using X-Sendfile with Django is:
- User requests URI to get a protected file
- Django app decides which file to return based on URL, and checks user permission, etc.
- Django app returns an HTTP Response with the 'X-Sendfile' header set to the server's file path
- The web server finds the file and returns it to the requester (I assume the webs server also strips out the 'X-Sendfile' header along the way)
Compared with chucking the file directly from Django, X-Sendfile seems likely to be a more efficient method of achieving protected downloads (since I can rely on Nginx to serve files, vs Django), but leaves 2 questions for me:
- Is my explanation of X-Sendfile at least abstractly correct?
- Is it really secure, assuming I don't provide normal, front-end HTTP access (e.g. http://www.example.com/downloads/secret-file.jpg) to the directory that the file is stored (ie, don't keep it in my
public_html
directory)? Or, could a tech-savvy user examine headers, etc. and reverse engineer a way to access a file (to then distribute)? - Is it really a big difference in performance. Am I going to bog my application server down by providing 8b chunked downloads of 150Mb files directly from Django, or is this sort-of a non-issue? The reason I ask is because if both versions are near equal, the Django version would be preferable due to my ability to do things in Python, like log the number of completed downloads, tally bandwidth of downloads etc.
Thanks in advance.
Django app returns an HTTP response with the X-Sendfile header set
, who is the recipient of that response? I guess it will be the web server (e.g. nginx). If that is the case, who initiated the request that is handled by the Django app in the first place? – Alarumget_file(request, file_name)
(something to that effect) and when a user visits the URL, return a response withX-Sendfile
pointing to the correct location for the named file (after adding whatever logic you want in the view to determine whether the user should be allowed to download the file). Nginx will intercept the response on its way out and return a response with the file (as a download). – Trinitrotoluenenginx
must be set up in front of theDjango
app server then? Otherwise, how cannginx
intercept the response on its way out? – Alarum