I am trying to protect files on my server (multiple types), with NGiNX and PHP.
Basically I want people to have to sign in to the website if they want to access those static files like images. DropBox does it very well. Where by they force you to sign in to access any static files you put on there server.
I though about using NGiNX Perl Module. And I would write a perl script that would check the session to see if the user was sign in to give them access to a static file.
I would prefer using PHP because all my code is running under PHP and I am not sure how to check a session created by PHP with PERL.
So basically my question is: How can I protect static files of any types that would need the user to have sign in and have a valid session created with a PHP script?
There are two things you are asking:
Hopefully this clarifies the role each component plays - although it may be a bit excessive.
Prevent External Access to files:
This part is done by your web server - in this case nginx.
In your nginx configuration (your server block), you specify a
root
path. By default all files under this root path are directly accessible.For instance, consider the following (the domain is 'example.com')
If you have a file,
uploaded_file.zip
, it will be accessible in the following ways:In essence, a file above the document root, will not be accessible via a browser, however, most configurations of PHP will allow your code to read the file, and deliver it (restrictions on this are often a result of
open_basedir
)In some scenarios, it may be preferable to have your files under the document root. To do this and still prevent (direct) external access, you will use the
internal
directive. For instance:location /uploads { internal; }
Now, any files placed in /var/www/example.com/public_html/uploads are only internally accessible (i.e. cannot be accessed via a browser, but can be accessed by your PHP scripts). If desired, you can also setup an alias on the /uploads location, so that another path can also be used to reference it.
At this point, your files are not directly accessible, but your scripts can still be able to serve them.
User Authentication and PHP:
Consider the following basic design: A user can access a file directly, or can go the login page. If they try to access a file directly and are logged in (and have permission), the file will download, otherwise, they will end up on the login screen. To upload a file, a user needs to be logged in.
Let's say that your download script (the page that will deliver the file to the user) is called 'download.php'. A typical URL may be example.com/download.php?file=uploaded_file.zip. It is quite likely that you don't want your URLs to include the php filename. To avoid this, you can setup a rewrite rule in your nginx config that will point another location (let's say /files) at your script. Add to your nginx config:
(Which amounts to changing the requested path of any requests starting with /files, and capturing everything after the / and passing it as a query parameter to your php file);
Now, your file can be accessed via: example.com/files/uploaded_file.zip (which internally redirects to your php script).
Your PHP file (download.php) now does the following:
Output the necessary headers (Content-Type, Content-Disposition, etc) and set:
X-Accel-Redirect: /uploads/uploaded_file.zip;
Note, you can do the actual download fully from PHP (e.g. using
readfile
)- it is just a bit more efficient, especially for large files) to do it via nginx. Also, despite the user appearing to access the file directly, internally, it is going through PHP, which is authenticating them before allowing them to continue.On the uploading side of things, you will
move_uploaded_file
to /var/www/example.com/public_html/uploads (which is protected by the 'internal' directive, and so, files cannot be directly accessed), and save permissions to your database.